An Abstract View of Priorities

[Previous] [Next]

When Microsoft developers designed the thread scheduler, they realized that it would not fit everyone's needs all the time. They also realized that the "purpose" of the computer would change over time. When Windows NT first came out, object linking and embedding (OLE) applications were just starting to be written. Now, OLE applications are commonplace. Game software is much more prevalent, and certainly the Internet wasn't discussed much in Windows NT's early days.

The scheduling algorithm has a significant effect on the types of applications that users run. From the beginning, Microsoft developers realized that they would need to modify the scheduling algorithm over time as the purpose of the system changed. But software developers need to write software today and Microsoft guarantees that your software will run on future versions of the system. How can Microsoft change the way the system works and still keep your software running? Here are a few answers:

  • Microsoft doesn't fully document the behavior of the scheduler.
  • Microsoft doesn't let applications take full advantage of the scheduler's features.
  • Microsoft tells you that the scheduler's algorithm is subject to change so that you can code defensively.

The Windows API exposes an abstract layer over the system's scheduler, so you never talk to the scheduler directly. Instead, you call Windows functions that "interpret" your parameters depending on the version of the system you're running on. So, in this chapter, I'll be discussing this abstract layer.

When you design an application, you should think about what other applications your user might run along with your application. Then you should choose a priority class based on how responsive you need the threads in your application to be. I know that this sounds vague; it's supposed to. Microsoft doesn't want to make any promises that will break your code in the future.

Windows supports six priority classes: idle, below normal, normal, above normal, high, and real-time. Of course, normal is the most common priority class and is used by 99 percent of the applications out there. The table below describes the priority classes.

Priority Class Description
Real-time The threads in this process must respond immediately to events in order to execute time-critical tasks. Threads in this process also preempt operating system components. Use this priority class with extreme caution.
High The threads in this process must respond immediately to events in order to execute time-critical tasks. The Task Manager runs at this class so a user can kill runaway processes.
Above normal The threads in this process run between the normal and high priority classes (new in Windows 2000).
Normal The threads in this process have no special scheduling needs.
Below normal The threads in this process run between the normal and idle priority classes (new in Windows 2000).
Idle The threads in this process run when the system is otherwise idle. This process is typically used by screensavers or background utility and statistic-gathering software.

The idle priority class is perfect for applications that run when the system is all but doing nothing. A computer that is not being used interactively might still be busy (acting as a file server, for example) and should not have to compete for CPU time with a screensaver. Statistic-tracking applications that periodically update some state about the system usually should not interfere with more critical tasks.

You should use the high priority class only when absolutely necessary. You might be surprised to learn that Windows Explorer runs at high priority. Most of the time Explorer's threads are suspended, waiting to be awakened when the user presses a key or clicks a mouse button. While Explorer's threads are suspended, the system doesn't assign its threads to a CPU, which allows lower-priority threads to execute. However, once the user presses a key or key combination, such as Ctrl+Esc, the system wakes up Explorer's thread. (The Start menu also appears when the user presses Ctrl+Esc.) If any lower-priority threads are executing, the system preempts those threads immediately and allows Explorer's thread to run.

Microsoft designed Explorer this way because users expect the shell to be extremely responsive, regardless of what else is going on in the system. In fact, Explorer's windows can be displayed even when lower-priority threads are hung in infinite loops. Because Explorer's threads have higher priority levels, the thread executing the infinite loop is preempted and Explorer lets the user terminate the hung process. Explorer is very well behaved—most of the time its threads have nothing to do and require no CPU time. If this were not the case, the whole system would perform much more slowly and many applications would not respond.

You should avoid the real-time priority class if possible. In fact, the early betas of Windows NT 3.1 did not expose this priority class to applications even though the operating system supported it. Real-time priority is extremely high and can interfere with operating systems tasks because most operating system threads execute at a lower priority. So real-time threads can prevent required disk I/O and network traffic from occurring. In addition, keyboard and mouse input are not processed in a timely manner; the user might think that the system is hung. Basically, you should have a good reason for using real-time priority—such as the need to respond to hardware events with short latency or to perform some short-lived task that just can't be interrupted.

NOTE
A process cannot run in the real-time priority class unless the user has the Increase Scheduling Priority privilege. Any user designated an administrator or a power user has this privilege by default.

Of course, most processes are part of the normal priority class. The two other priority classes, below normal and above normal, are new in Windows 2000. Microsoft added these because several companies complained that the existing priority classes didn't offer enough flexibility.

Once you select a priority class, you should stop thinking about how your application interrelates with other applications and just concentrate on the threads within your application. Windows supports seven relative thread priorities: idle, lowest, below normal, normal, above normal, highest, and time-critical. These priorities are relative to the process's priority class. Again, most threads use the normal thread priority. The table below describes the relative thread priorities.

Relative Thread Priority Description
Time-critical Thread runs at 31 for the real-time priority class and at 15 for all other priority classes.
Highest Thread runs two levels above normal.
Above normal Thread runs one level above normal.
Normal Thread runs normally for the process's priority class.
Below normal Thread runs one level below normal.
Lowest Thread runs two levels below normal.
Idle Thread runs at 16 for the real-time priority class and at 1 for all other priority classes.

So, to summarize, your process is part of a priority class and you assign the threads within the process relative thread priorities. You'll notice that I haven't said anything about priority levels 0 through 31. Application developers never work with priority levels. Instead, the system maps the process's priority class and a thread's relative priority to a priority level. It is precisely this mapping that Microsoft does not want to commit to. In fact, this mapping has changed between versions of the system.

The following table shows how this mapping works for Windows 2000, but be aware that earlier versions of Windows NT and certainly Windows 95 and Windows 98 have slightly different mappings. Also be aware that the mapping will change in future versions of Windows.

For example, a normal thread in a normal process is assigned a priority level of 8. Since most processes are of the normal priority class and most threads are of normal thread priority, most threads in the system have a priority level of 8.

If you have a normal thread in a high-priority process, the thread will have a priority level of 13. If you change the process's priority class to idle, the thread's priority level becomes 4. Remember that thread priorities are relative to the process's priority class. If you change a process's priority class, the thread's relative priority will not change but its priority level will.

Process Priority Class
Relative Thread Priority Idle Below Normal Normal Above Normal High Real-Time
Time-critical 15 15 15 15 15 31
Highest 6 8 10 12 15 26
Above normal 5 7 9 11 14 25
Normal 4 6 8 10 13 24
Below normal 3 5 7 9 12 23
Lowest 2 4 6 8 11 22
Idle 1 1 1 1 1 16

Notice that the table above does not show any way for a thread to have a priority level of 0. This is because the 0 priority is reserved for the zero page thread and the system does not allow any other thread to have a priority of 0. Also, the following priority levels are not obtainable: 17, 18, 19, 20, 21, 27, 28, 29, or 30. If you are writing a device driver that runs in kernel mode, you can obtain these levels; a user-mode application cannot. Also note that a thread in the real-time priority class can't be below priority level 16. Likewise, a thread in a non-real-time priority class cannot be above 15.

NOTE
The concept of a process priority class confuses some people. They think that this somehow means that processes are scheduled. Processes are never scheduled; only threads are scheduled. The process priority class is an abstract concept that Microsoft created to help isolate you from the internal workings of the scheduler; it serves no other purpose.

NOTE
In general, a thread with a high priority level should not be schedulable most of the time. When the thread has something to do, it quickly gets CPU time. At this point, the thread should execute as few CPU instructions as possible and go back to sleep, waiting to be schedulable again. In contrast, a thread with a low priority level can remain schedulable and execute a lot of CPU instructions to do its work. If you follow these rules, the entire operating system will be responsive to its users.



Programming Applications for Microsoft Windows
Programming Applications for Microsoft Windows (Microsoft Programming Series)
ISBN: 1572319968
EAN: 2147483647
Year: 1999
Pages: 193

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net