Thread Scheduling and Prioritizing
This section looks at how you can change the scheduling priority of a thread in UNIX and Windows. Ideally, you want to map Windows priority classes to UNIX scheduling policies and Windows thread priority levels to UNIX priority levels, but unfortunately, it is not this simple. The priority level of a Windows thread is determined by both the priority class of its process and its priority level. The priority class and priority level are combined to form the base priority of each thread. Every thread in Windows has a base priority level determined by the priority value of the thread and the priority class of its owning process. The operating system uses the base priority level of all executable threads to determine which thread gets the next slice of CPU time. Threads are scheduled in a round-robin fashion at each priority level, and scheduling of threads at a lower level will only take place when there are no executable threads at a higher level. UNIX offers both round-robin and FIFO scheduling algorithms, whereas Windows uses only round-robin. This does not mean that Windows is less flexible; it just means that any fine-tuning that was performed on thread scheduling in UNIX has to be implemented differently when using Windows. Table Z lists the base priority levels for combinations of priority class and priority value for Windows.
Table Z: Process and Thread Priority for Windows
Process Priority Class |
Thread Priority Level |
|
1 |
IDLE_PRIORITY_CLASS |
THREAD_PRIORITY_IDLE |
1 |
BELOW_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_IDLE |
1 |
NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_IDLE |
1 |
ABOVE_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_IDLE |
1 |
HIGH_PRIORITY_CLASS |
THREAD_PRIORITY_IDLE |
2 |
IDLE_PRIORITY_CLASS |
THREAD_PRIORITY_LOWEST |
3 |
IDLE_PRIORITY_CLASS |
THREAD_PRIORITY_BELOW_NORMAL |
4 |
IDLE_PRIORITY_CLASS |
THREAD_PRIORITY_NORMAL |
4 |
BELOW_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_LOWEST |
5 |
IDLE_PRIORITY_CLASS |
THREAD_PRIORITY_ABOVE_NORMAL |
5 |
BELOW_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_BELOW_NORMAL |
5 |
Background NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_LOWEST |
6 |
IDLE_PRIORITY_CLASS |
THREAD_PRIORITY_HIGHEST |
6 |
BELOW_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_NORMAL |
6 |
Background NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_BELOW_NORMAL |
7 |
BELOW_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_ABOVE_NORMAL |
7 |
Background NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_NORMAL |
7 |
Foreground NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_LOWEST |
8 |
BELOW_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_HIGHEST |
8 |
NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_ABOVE_NORMAL |
8 |
Foreground NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_BELOW_NORMAL |
8 |
ABOVE_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_LOWEST |
9 |
NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_HIGHEST |
9 |
Foreground NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_NORMAL |
9 |
ABOVE_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_BELOW_NORMAL |
10 |
Foreground NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_ABOVE_NORMAL |
10 |
ABOVE_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_NORMAL |
11 |
Foreground NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_HIGHEST |
11 |
ABOVE_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_ABOVE_NORMAL |
11 |
HIGH_PRIORITY_CLASS |
THREAD_PRIORITY_LOWEST |
12 |
ABOVE_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_HIGHEST |
12 |
HIGH_PRIORITY_CLASS |
THREAD_PRIORITY_BELOW_NORMAL |
13 |
HIGH_PRIORITY_CLASS |
THREAD_PRIORITY_NORMAL |
14 |
HIGH_PRIORITY_CLASS |
THREAD_PRIORITY_ABOVE_NORMAL |
15 |
HIGH_PRIORITY_CLASS |
THREAD_PRIORITY_HIGHEST |
15 |
HIGH_PRIORITY_CLASS |
THREAD_PRIORITY_TIME_CRITICAL |
15 |
IDLE_PRIORITY_CLASS |
THREAD_PRIORITY_TIME_CRITICAL |
15 |
NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_TIME_CRITICAL |
15 |
BELOW_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_TIME_CRITICAL |
15 |
ABOVE_NORMAL_PRIORITY_CLASS |
THREAD_PRIORITY_TIME_CRITICAL |
16 |
REALTIME_PRIORITY_CLASS |
THREAD_PRIORITY_IDLE |
17 |
REALTIME_PRIORITY_CLASS |
-7 |
18 |
REALTIME_PRIORITY_CLASS |
-6 |
19 |
REALTIME_PRIORITY_CLASS |
-5 |
20 |
REALTIME_PRIORITY_CLASS |
-4 |
21 |
REALTIME_PRIORITY_CLASS |
-3 |
22 |
REALTIME_PRIORITY_CLASS |
THREAD_PRIORITY_LOWEST |
23 |
REALTIME_PRIORITY_CLASS |
THREAD_PRIORITY_BELOW_NORMAL |
24 |
REALTIME_PRIORITY_CLASS |
THREAD_PRIORITY_NORMAL |
25 |
REALTIME_PRIORITY_CLASS |
THREAD_PRIORITY_ABOVE_NORMAL |
26 |
REALTIME_PRIORITY_CLASS |
THREAD_PRIORITY_HIGHEST |
27 |
REALTIME_PRIORITY_CLASS |
3 |
28 |
REALTIME_PRIORITY_CLASS |
4 |
29 |
REALTIME_PRIORITY_CLASS |
5 |
30 |
REALTIME_PRIORITY_CLASS |
6 |
31 |
REALTIME_PRIORITY_CLASS |
THREAD_PRIORITY_TIME_CRITICAL |
Managing Thread Priorities in Windows
The Windows API provides a number of functions for managing thread priorities, including the following:
1. GetThreadContext(). This function returns the execution context of the specified thread. The following is an example showing the thread context:
CONTEXT context;
WCHAR szBuffer[128];
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
GetThreadContext(GetCurrentThread(),&context);
wprintf(LCS=%X, EIP=%X, FLAGS=%X, DR1=%X\n,context.SegCs, context.Eip, context.EFlags,context.Dr1);
2. GetThreadPriority(). This function returns the assigned thread priority level for the specified thread. To see how thread priority affects the system, a simple test, such as the one that follows, could be added to a simple Windows application:
SetThreadPriority(GetCurrentThread(),
THREAD_PRIORITY_LOWEST);
DWORD dwTicks = GetTickCount();
long i, j;
for(i = 0; i < 200000; i ++)
for(j = 0; j < 2000; j ++)
wprintf(LTest time=%ld\n, GetTickCount() – dwTicks);
Adjusting the thread priority should yield different time deltas.
3. GetThreadPriorityBoost(). This function retrieves the priority boost control state of the specified thread. Threads have dynamic priority, which is the priority that the scheduler uses to identify which thread will execute. Initially, the priority of a thread is the same as its base priority, but the system may increase or decrease the priority to maintain thread responsiveness. Only threads with a priority between 0 and 15 are eligible for dynamic priority boost. The system boosts the dynamic priority of a thread to enhance its responsiveness as follows:
4. SetThreadIdealProcessor(). This function specifies the preferred processor for a specific thread. The system schedules threads on the preferred processor when possible.
5. SetThreadPriority(). This function changes the priority level for a thread.
6. SetThreadPriorityBoost(). This function enables or disables dynamic priority boosts by the system.