The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →“Inside the Windows NT Scheduler, Part 1” is Mark Russinovich’s historical technical article about the Windows NT 4.0 kernel scheduler. Published in Windows NT Magazine on July 1, 1997, it explains how a uniprocessor system chooses among runnable threads, assigns priorities and quantums, performs preemption, and uses temporary priority boosts to balance responsiveness with fairness. It is about kernel CPU scheduling—not the later Windows Task Scheduler used to launch jobs at a scheduled time.
The original article is available through Windows IT Pro/ITPro Today. Russinovich’s publication archive lists its August 1997 companion, Part 2, which examines multiprocessor scheduling.
What the article is—and is not
This is an explanatory magazine article, not an official Microsoft specification or a current guide to Windows 10, Windows 11, or Windows Server. Its numerical examples and implementation descriptions belong to the Windows NT 4.0 era. Part 1 concentrates on a single-processor machine; the companion article handles symmetric multiprocessing (SMP), affinity, processor selection, migration, and cache locality.
| Fact | Historical detail |
|---|---|
| Author | Mark Russinovich |
| Publication | Windows NT Magazine, July 1, 1997 |
| Platform discussed | Windows NT 4.0 |
| Main scope | Thread scheduling on a uniprocessor |
| Companion | Part 2, published August 1, 1997, on multiprocessor scheduling |
The problem NT’s scheduler had to solve
Windows NT was preemptive and multithreaded. Many threads could be ready to run, but a uniprocessor could execute only one at a time. The kernel therefore needed rules for selecting the next thread and deciding when the current one should be replaced.
Recommended Free Tools
#1 Best Overall
Russinovich presents scheduling as a compromise among several goals:
- Priority: important work should receive preference.
- Responsiveness: interactive or newly awakened work should react quickly.
- Fairness: runnable threads should not be ignored indefinitely.
- Throughput: the system should complete useful work efficiently.
- Starvation avoidance: strict priority must not permanently block lower-priority work.
There is no single winning metric. Shorter time slices can make interaction feel faster but cause more context-switch overhead; longer slices can favor CPU-bound throughput while delaying other work.
Why NT schedules threads rather than processes
A process owns a virtual address space and resources such as handles. A thread is an execution path inside that process, with its own register state and scheduling attributes. A process may contain one thread or many.
The scheduler compares runnable threads, not processes as indivisible units. Two threads in one process can have different priorities, block on different objects, and take different turns on the CPU. A thread can be runnable yet not executing because another ready thread has a higher priority.
Rank #2
NT 4.0’s priority model
The article describes a numerical range from 1 through 31. Priority 0 is reserved for the system idle thread. Priorities 1–15 are the dynamic range normally used by application threads; 16–31 are the real-time range. A larger number means a stronger scheduling preference.
For the NT 4.0 model discussed, Russinovich states that Administrator privileges were required to place ordinary programs in the real-time range. That is a period-specific privilege description, not a universal rule for every later Windows release.
Win32 process classes
Win32 applications selected priority in two stages: a process priority class established a base, then a relative thread priority adjusted the thread within that class.
| Process class | Base priority described in the article |
|---|---|
| Realtime | 24 |
| High | 13 |
| Normal | 8 |
| Idle | 4 |
The relative modifiers were:
| Relative setting | Adjustment |
|---|---|
| Highest | +2 |
| Above normal | +1 |
| Normal | 0 |
| Below normal | −1 |
| Lowest | −2 |
The article also describes special TIME_CRITICAL and IDLE modifiers that move a thread to the top or bottom of its applicable dynamic or real-time range. These values explain Russinovich’s 1997 account; they should not be treated as a complete description of contemporary Windows scheduling APIs, processor groups, multimedia scheduling, or power management.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
Rank #3
Quantums: the unit of a turn
A quantum is the scheduler’s allotted unit of processor time. When a thread runs, its quantum eventually expires, giving the scheduler an opportunity to select another ready thread. Repeated short turns create the appearance of simultaneous execution on one CPU.
Russinovich gives period-specific x86 examples:
| System | Example quantum | Qualification |
|---|---|---|
| Windows NT Server | Typically 120 milliseconds | 1997-era user-thread example |
| Windows NT Workstation | 20, 40, or 60 milliseconds | Varied with system settings and foreground/background treatment |
These are not current Windows timing guarantees. Edition, architecture, configuration, and later scheduler changes all matter.
When does NT reconsider the running thread?
The article identifies the main events that cause a scheduling decision:
- Quantum expiration: the running thread uses its allotted turn.
- Blocking: it waits for I/O, an event, a mutex, or another synchronization condition.
- Termination or voluntary yield: it can no longer continue running.
- A blocked thread becomes ready: newly runnable work may outrank the current thread.
- A higher-priority thread becomes runnable: preemption can occur immediately rather than waiting for the current quantum to end.
Quantum expiration alone does not mean that any arbitrary thread replaces the current one. A higher-priority ready thread always has precedence; equal-priority threads compete according to the ready-queue and quantum rules.
Rank #4
The Dispatcher Ready List
The Dispatcher Ready List is the kernel’s collection of priority-organized queues containing threads eligible to execute but not currently running. Conceptually, the scheduler searches from the highest priority downward until it finds a nonempty queue.
The basic selection loop is:
- Examine the ready queues.
- Find the highest-priority queue containing a runnable thread.
- Select a thread from that queue according to queue order and current quantum state.
- Dispatch it on the processor.
- Repeat when the thread blocks, yields, terminates, is preempted, or exhausts its quantum.
The same ready-list concept matters in SMP systems, but multiple processors then need synchronization while changing or searching the structure. That is one reason Part 2 requires a separate treatment.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.A uniprocessor example
Consider an illustrative state—not a verbatim example from the article:
- Thread A is running at priority 8.
- Thread B, at priority 10, becomes ready after an event is signaled.
- Thread C, also at priority 8, is already waiting in the ready queue.
Because B has the highest runnable priority, it preempts A. C does not preempt A merely by becoming ready: it has the same priority, so it competes through same-priority queue order and quantum behavior. If B later blocks, terminates, yields, or gives up the processor, the scheduler searches again and may dispatch A or C.
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware matchBest Value
Dynamic priorities, boosts, and starvation prevention
Strict fixed priorities can produce poor interactive behavior. A CPU-bound thread may consume successive quantums while a thread that has been waiting for input or synchronization becomes ready only briefly. NT therefore used dynamic adjustments and selected priority boosts.
A boost is a temporary scheduling preference, not a permanent rewrite of an application’s base priority. It can help a thread respond after waiting or completing an operation that merits prompt service. Temporary increases must eventually decay or be constrained; otherwise one boosted thread could dominate the CPU indefinitely.
The article presents priority boosting and starvation prevention as complementary mechanisms. Boosting improves responsiveness in selected cases, while the scheduler’s broader policy ensures that lower-priority runnable work is not forgotten forever. The original discussion does not justify assigning one universal boost amount to every I/O or wait operation.
What Part 1 leaves to Part 2
Part 1’s single-processor model avoids decisions that arise when several CPUs can run threads simultaneously. Russinovich’s companion Part 2 covers:
- symmetric multiprocessing;
- hard and soft affinity;
- ideal processors;
- the
FindReadyThreadandReadyThreaddecisions; - thread migration and cache locality;
- scalability trade-offs and period-specific processor limits.
Part 2 restates the principal triggers for scheduling and examines how they change when more than one processor can make scheduling decisions. The author’s publication archive also records historical errata for Part 2, including corrections involving ideal processors and KiReadyThread: Sysinternals publication archive.
Why the article still matters
For students and kernel historians, the article provides a compact model of NT’s design: threads are the dispatchable units, priorities select among ready work, quantums provide bounded turns, and dynamic adjustments reconcile responsiveness with fairness. It also shows why a scheduler cannot be judged by CPU utilization alone; turnaround time, predictability, context-switch cost, and starvation resistance matter too.
Its limits are equally important. The article does not specify every kernel implementation detail, does not describe all later NT-derived releases, and should not be read as documentation for the modern Windows scheduler. Its value is historical and conceptual: it explains how Windows NT 4.0’s uniprocessor scheduler was presented in 1997 and establishes the foundation for understanding the multiprocessor issues treated in Part 2.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




