Nice low high default BSD 20 -20 10(or 0?) SV 0 39 20 priocntl -l -d PID -s -p # (PID|pgm [args]) -s -c CLASS -m # (PID|pgm [args]) dispadmin -l -g -c CLASS -r 100 -g -s somefile #100 is number of seconds vs millisec Priorities in Solaris 0-169 (if RT loaded) 0-115 (if no RT loaded) Classes Interrupt threads RT (real time) SYS (kernel) IA (interactive) TS (timesharing) The AnswerBook contains a discussion about process scheduling. In Solaris, highest priorities are scheduled first. Kernel thread scheduling information can be revealed with ps -elcL. A process can exist in one of the following states: running, sleeping or ready. The following scheduling classes exist in Solaris: Timesharing (TS): Normal user work. The CPU is shared in rotation between threads at the same priority via time slicing. Compute-bound operations have their priority lowered and I/O-bound operations have their priorities raised. Interactive (IA): Interactive class. This class is the same as the TS class plus a priority boost that is given to the task in the active window. System (SYS): Kernel priorities. This class is used for system threads (eg page daemon). Threads in this class do not share the CPU via time slicing; they run until finished or pre-empted. This class also features fixed priority levels. Real Time (RT): Used for processes that require immediate system access, usually critical hardware systems. This class has the highest priority except for interrupt handling. The CPU is shared via time slicing if there are several threads with the same priority. Real time threads have a fixed priority for the duration of their lives. If the RT scheduling class has not been activated, then TS and IA processes will have priorities between 0 and 59, SYS threads will have priorities of 60-99, and interrupt threads will have priorities between 100 and 109. If RT has been activated, TS, IA and SYS will be as above. RT will have priorities between 100 and 159, and interrupt threads will have priorities between 160 and 169. Time Slicing TS and IA scheduling classes implement an adaptive time slicing scheme that increases the priority of I/O-bound processes at the expense of compute-bound processes. The exact values that are used to implement this can be found in the dispatch table. To examine the TS dispatch table, run the command dispadmin -c TS -g. (If units are not specified, dispadmin reports time values in ms.) The following values are reported in the dispatch table: ts_quantum: This is the default length of time assigned to a process with the specified priority. ts_tqexp: This is the new priority that is assigned to a process that uses its entire time quantum. ts_slpret: The new priority assigned to a process that blocks before using its entire time quantum. ts_maxwait: If a thread does not receive CPU time during a time interval of ts_maxwait, its priority is raised to ts_lwait. ts_lwait: The man page for ts_dptbl contains additional information about these parameters. dispadmin can be used to edit the dispatch table to affect the decay of priority for compute-bound processes or the growth in priority for I/O-bound processes. Obviously, the importance of the different types of processing on different systems will make a difference in how these parameters are tweaked. In particular, ts_maxwait and ts_lwait can prevent CPU starvation, and raising ts_tqexp slightly can slow the decline in priority of CPU-bound processes. In any case, the dispatch tables should only be altered slightly at each step in the tuning process, and should only be altered at all if you have a specific goal in mind. The following are some of the sorts of changes that can be made: Decreasing ts_quantum favors IA class objects. Increasing ts_quantum favors compute-bound objects. ts_maxwait and ts_lwait control CPU starvation. ts_tqexp can cause compute-bound objects' priorities to decay more or less rapidly. ts_slpret can cause I/O-bound objects' priorities to rise more or less rapidly. RT objects time slice differently in that ts_tqexp and ts_slpret do not increase or decrease the priority of the IA objects add 10 to the regular TS priority of the process in the active window. This priority shifts with the focus on the active window. object. Each RT thread will execute until its time slice is up or it is blocked while waiting for a resource. Callouts Solaris handles callouts with a callout thread that runs at maximum system priority, which is still lower than any RT thread. RT callouts are handled separately and are invoked at the lowest interrupt level, which ensures prompt processing. Priority Inheritance Each thread has two priorities: global priority and inherited priority. The inherited priority is normally zero unless the thread is sitting on a resource that is required by a higher priority thread. When a thread blocks on a resource, it attempts to "will" or pass on its priority to all threads that are directly or indirectly blocking it. The pi_willto() function checks each thread that is blocking the resource or that is blocking a thread in the syncronization chain. When it sees threads that are a lower priority, those threads inherit the priority of the blocked thread. It stops traversing the syncronization chain when it hits an object that is not blocked or is higher priority than the willing thread. This mechanism is of limited use when considering condition variable, semaphore or read/write locks. In the latter case, an owner-of-record is defined, and the inheritance works as above. If there are several threads sharing a read lock, however, the inheritance only works on one thread at a time. Thundering Herd When a resource is freed, all threads awaiting that resource are woken. This results in a footrace to obtain access to that object; one succeeds and the others return to sleep. This can lead to wasted overhead for context switches, as well as a problem with lower priority threads obtaining access to an object before a higher-priority thread. This is called a "thundering herd" problem. Priority inheritance is an attempt to deal with this problem, but some types of syncronization do not use inheritance. Turnstiles Each syncronization object (lock) contains a pointer to a structure known as a turnstile. These contain the data needed to manipulate the syncronization object, such as a queue of blocked threads and a pointer to the thread that is currently using the resource. Turnstiles are dynamically allocated based on the number of allocated threads on the system. A turnstile is allocated by the first thread that blocks on a resource and is freed when no more threads are blocked on the resource. Turnstiles queue the blocked threads according to their priority. Turnstiles may issue a signal to wake up the highest-priority thread, or they may issue a broadcast to wake up all sleeping threads. Adjusting Priorities The priority of a process can be adjusted with priocntl or nice, and the priority of an LWP can be controlled with priocntl(). Real Time Issues STREAMS processing is moved into its own kernel threads, which run at a lower priority than RT threads. If an RT thread places a STREAMS request, it may be serviced at a lower priority level than is merited. Real time processes also lock all their pages in memory. This can cause problems on a system that is underconfigured for the amount of memory that is required. Since real time processes run at such a high priority, system daemons may suffer if the real time process does not permit them to run. When a real time process forks, the new process also inherits real time privileges. The programmer must take care to prevent unintended consequences. Loops can also be hard to stop, so the programmer also needs to make sure that the program does not get caught in an infinite loop. Interrupts Interrupt levels run between 0 and 15. Some typical interrupts include: soft interrupts SCSI/FC disks (3) Tape, Ethernet Video/graphics clock() (10) serial communications real-time CPU clock Nonmaskable interrupts (15)