Scheduling Priority
Under Solaris, the legal range of thread priority values and the default priorities depend on the current contention scope and scheduling policy.
Scheduling Priority For Process-Scope Threads. For unbound, or process-scope threads, Solaris allows any priority value in the range between 0 and MAX_INT. Process scope threads are scheduled onto LWPs according to this priority value.
Solaris maintains a separate scheduling queue for each thread priority value up to 127. Priority values greater that 127 share a single queue, forcing the Solaris threads scheduler to traverse the entire queue each time another thread must be scheduled.
For this reason, the Threads Module limits the Solaris process-scope priority range to a minimum of 0 and a maximum of 127. If the inheritance policy is RW_THR_INHERIT, a new thread’s priority is inherited from the creating thread, and if the inheritance policy is RW_THR_EXPLICIT, the default priority is 0.
How are process-scope threads scheduled at the system level? That depends on the scheduling attributes of the LWP pool that is used to execute the unbound threads. When a process is created, the initial LWP in the process inherits its scheduling class and priority from the parent process. Each LWP created to execute unbound threads inherits its scheduling class and priority from this initial LWP. This means that all LWPs used for unbound threads will possess the same scheduling parameters.
Scheduling Priority For System-Scope Threads. When a thread is given system contention scope in the Solaris implementation of the Threads Module, that thread is permanently bound to an LWP.
These system-scope threads are scheduled using two separate priority values; one priority value defines the system-level scheduling, or LWP priority of the thread, while the second value is used to resolve any contention for thread-level synchronization resources shared with other threads in the same process (such as a mutex created with the USYNC_THREAD flag).
The process-level, synchronization priority is called the process scope priority value, while the system-level scheduling priority is called the system-scope priority value.
The RWThreadAttribute class provides two additional sets of member functions for use in independently manipulating these two priority values. The regular priority functions may still be used; but it should be understood that these functions are limited to manipulating the priority value corresponding to the current contention scope; when the contention scope is RW_THR_PROCESS_SCOPE, the regular priority functions do the same thing as the process-scope priority functions, and when the contention scope is RW_THR_SYSTEM_SCOPE, the regular priority functions do the same thing as the system-scope priority functions.
You cannot get or set the system-scope priority value when the contention scope is RW_THR_PROCESS_SCOPE; any attempt to do so will result in an exception.
You only need to define a separate process-scope priority for a system-scope thread when you have used more than one priority value for your process-scope threads, and there exists the possibility that your system-scope thread may deadlock as a result of priority inversion because it assumed the default process-scope priority value.
The range of process-scope priority values remains unchanged regardless of contention scope and scheduling policy, while the system-scope priority values can vary with scheduling policy.
To determine the range of priority values for the various system-scope policies, use the getMinPriority() or getMinSystemScopePriority()and getMaxPriority() or getMaxSystemScopePriority() functions to retrieve the minimum and maximum allowable values. The minimum priority value for system-scope threads is always 0. The maximum priority values are defined as part of the operating system configuration on each workstation; the maximum can vary significantly from machine to machine.
If the scheduling policy value of an RWThreadAttribute instance is RW_THR_TIME_SLICED_DYNAMIC, you will not be able to set, get, or query the legal range for the priority, or system-scope priority attribute values, unless the process has the super-user privilege. If the current process does not have this privilege, you will have to wait until the thread has been created and perform operations on the active thread.
In either case, when the desired or current scheduling policy is RW_THR_TIME_SLICED_DYNAMIC, the Threads Module must consider several factors in determining the maximum allowable priority value:
*The current privileges of the process.
*The maximum user-priority level supported by the time-sharing (TS) class.
*The time-sharing user-priority limit, if any, associated with the LWP of the calling thread (the calling thread is assumed to be the creating thread). The LWP of a bound thread inherits this value from the creating LWP, but only if the creating LWP is assigned to the time-sharing class. If not inherited, the default user-priority limit for an LWP is 0. The Threads Module will automatically adjust the user priority limit back up to the maximum priority value supported by the time-sharing class, but only if the process has the super-user privilege.
This information is used to determine whether the user-priority limit can be adjusted up to the maximum priority value, and if not, what maximum priority value can be expected. To make this determination the Threads Module:
*Uses the Solaris priocntl() function to determine the maximum user-priority supported by the time-sharing class. This value is defined as part of the operating system configuration, and can vary from machine to machine. If the process has the super-user privilege, as determined by a call to the geteuid() function, the Threads Module makes the assumption that it will be able to override the user-priority limit that is inherited on a per-LWP basis, and the maximum priority will be that of the Time-Share class.
*If the process does not have super-user privilege, then the Threads Module cannot determine the maximum priority value for a thread until the thread is created, because the user-priority limit will not be known until that time.
When the scheduling policy is RW_THR_TIME_SLICED_FIXED or RW_THR_PREEMPTIVE, the LWP associated a newly-created bound thread is assigned to the real-time (RT) scheduling class. The Threads Module retrieves the maximum priority for these policies by using the priocntl() function to query the real-time class for the maximum priority value supported by that class. This value is defined as part of the operating system configuration, and can vary from machine to machine. To use either one of these policies requires the super-user privilege.
Scheduling Priority Inheritance. A new thread’s priority value is inherited from the creating thread, unless the priority attribute has been explicitly set or the inheritance policy is set to RW_THR_EXPLICIT. If the inheritance policy is RW_THR_EXPLICIT, the Threads Module defines the default priority to be 0, as shown in the following table:
Table 10 – Solaris native thread support: Setting of scheduling priority values
Contention Scope
Scheduling Policy
Default Process-Scope Priority
Default System-Scope Priority
Process
RW_THR_PREEMPTIVE
Inherited or 0
N/A
RW_THR_TIME_SLICED_DYNAMIC
Inherited or 0
Inherited or 0
System
RW_THR_TIME_SLICED_FIXED
Inherited or 0
Inherited or 0
RW_THR_PREEMPTIVE
Inherited or 0
Inherited or 0
If you change the scheduling contention scope or policy attributes, the Threads Module will check that the priority values are still legal under the new settings, and if not, will force the priority values the appropriate defaults.