Last edit: 05-03-17 Graham Wideman |
Data Acquisition |
Multitasking Discussion Article created: 99-06-16 |
In order to understand timing issues under Windows it's necessary to understand how multitasking works for these operating systems.
The operating system views each application and service as a process, which may incorporate 1 or more threads of execution. A key part of the OS is the mechanism which runs applications and services, and provides the approximate effect of running them all at once (multitasking) by allocating time slices to each in turn according to priority levels. The W95/98/NT/2000 operating systems are refered to as preemptive mulitasking because at regular intervals the OS "preempts" whichever thread is running in order to reevaluate which is the most deserving thread.
So, of great pertinence to the subject of timing are the following issues:
Overall thread priority is determined by three factors:
An exhaustive table of priority combinations is given in the MSDN reference above. I've summarized the resulting overall priorities in the following table.
Process "Priority_Class" | ||||||
Thread Priority | Idle | Below_Normal (NT5) |
Normal | Above_Normal (NT5) |
High | RealTime |
Idle | 1 | 1 | 1 | 1 | 1 | 16 |
Lowest | 2 | 4 | 5 Bg / 7 Fg | 8 | 11 | 22 |
Below_Normal | 3 | 5 | 6 Bg / 8 Fg | 9 | 12 | 23 |
Normal | 4 | 6 | 7 Bg / 9 Fg | 10 | 13 | 24 |
Above_Normal | 5 | 7 | 8 Bg? / 10 Fg | 11 | 14 | 25 |
Highest | 6 | 8 | 9 Bg? / 11 Fg | 12 | 15 | 26 |
Time_Critical | 15 | 15 | 15 | 15 | 15 | 31 |
Notes
Bg and Fg indicate Background and Foreground. "Bg?" means that the MSDN chart doesn't specifically indicate background, but elsewhere provides a value for Foreground.
Boost
The table above doesn't include the details of the Boost mechanism, see the MSDN reference for details. In brief, the scheduler may boost the priority of certain threads under certain circumstances, including the thread being part of a process that came to the foreground, or it's a thread that just became ready. The boost strategy varies by OS, and may be impacted by user settings.
Priority Inversion
Each OS includes a strategy to avoid getting stuck when a a high-priority thread is waiting for a low-priority thread that can't get a time-slice. See MSDN for details.
Other interesting features:
This would
be of most concern if when writing an app which is supposed to service hardware on a
timely basis (ie: you don't have a low-level driver for the hardware), and you are trying
to use callbacks or thread wake-ups to do this. In either case, the callback or thread
wake-up will only occur at the requested time if higher-priority threads are not running
or waiting. This would tempt the programmer to run such a service thread at as high a
priority as possible.
MSDN documents advise:
You should almost never use REALTIME_PRIORITY_CLASS, because this interrupts system
threads that manage mouse input, keyboard input, and background disk flushing. This class
can be appropriate for applications that "talk" directly to hardware or that
perform brief tasks that should have limited interruptions.
So the following factors may make it feasible to set the app to RealTime process priority. (I haven't tried these, they just seem plausible from the documentation.)
On what interval does the scheduler check the time, and take a look at the process/thread queue? This will determine several items of interest to us:
Scheduler time-slice granularity (quantum) is discussed in the System Internals references and elsewhere. They report that, it's generally a multiple of 20 ms. Here's the table, according to System Internals site:
Quantum size [ms] according to System Internals |
|||
Boost | |||
Platform | None | Low | Max |
NT 4 Workstation | 20 | 40 | 60 |
NT 4 Server | 120 | 120 | 120 |
Of interest:
However, this misses some crucial points:
Setting Scheduler to High Res: Scheduler granularity has some "normal" value, but can be set to a higher-resolution value by using the timeBeginPeriod and timeEndPeriod functions. Indeed, on a generic PC running W95 or NT4, it can be set to 1 millisec.
Scheduler Granularity Normally 10 millisec? Contrary to what's written elsewhere, I found that the normal scheduler granularity appears to be 10 millisec, both in NT Workstation, and on Win95. You can use my SkedGran demo app to see what you get.
Scheduler Period Regular? Supposing that the scheduler is using 10 millisec periods, what happens if a thread finishes before its time slot is used up? Presumably the scheduler just checks the queue, assigning the next thread 10 millisecs, and so forth. This means that the the times that the scheduler gets control will not necessarily be evenly spaced, often being 10 millisecs apart, but sometimes shorter.
1. Regardless of the millisec-level scheduling that you can get for your application code most of the time, under Win95 or NT you can't get it all the time. This may be good enough for what you want to do -- but to evaluate this you'll probably need to build an app that monitors and reports how consistently your app's code gets scheduled in your target environment -- and reports on the distribution of delays that it sees.
2. Does code scheduled in a driver fare any better? This presumably depends on how the scheduler shares time with drivers, and how driver priority works relative to application priority -- topics I haven't explored. If someone has a brief explanation on this, let me know!
[Up to: Data Acquisition Topics]