The key to understanding Windows NT thread scheduling and resultant application behavior is knowing the central algorithm used. This algorithm is very simple and is the same one a number of other operating systems use: the highest priority ready thread gets run. A list of ready threads or processes exists, which is often called the dispatch queue or eligible queue. The queue entries are in order based on their individual priority. A hardware-driven real-time clock or interval timer will periodically interrupt, passing control to a device driver that calls the process or thread scheduler. The thread scheduler will take the highest priority entry from the queue and dispatch it to run.
Therefore, a hardware event drives the regular examination of thread states and the evaluation of which thread will run next. The frequency of this operation is quite rapid, often from 10 to 32 milliseconds on most systems.
Neither Windows NT nor many other operating systems use CPU quotas. The scheduling algorithm merely selects the highest priority ready-to-run thread and allows it to run uninterrupted until the next clock tick, at which time the scheduler gets control and reevaluates which thread has the highest priority and is ready to run. However, if the previously running thread still has the highest priority and is still ready to run—has not blocked on I/O or otherwise changed states—it will be run again.
Also, there is essentially no gradual or proportional control over the amount of CPU time a compute-bound thread receives. Often the misconception exists that by lowering the priority of a compute-bound thread by a certain amount, the CPU time will decrease proportionally. In actuality, it will receive just as much time as before because it has a higher priority than other threads. For example, a compute-bound thread could be diminished from priority 31 to 16, and as long as all other threads are at 15 or below, it will receive just as much time at 16 as at 31, and its system impact will be just as great.
The scheduler attempts to minimize this situation for threads in the variable class, which ranges from 1 to 15. However, highly compute-bound threads can still degrade overall system responsiveness in some circumstances. You can usually investigate these situations in the following way:
You will usually see the compute-bound thread has an equal or higher priority than the others.
Schedulers of this type work remarkably well in a wide variety of situations, are well understood, and have low overhead. However, especially with compute-bound processes, they have limitations that are difficult to overcome. In these situations, the compute-bound process tends to get either all the available CPU time or little to none. It is very hard to throttle a compute-bound process so that it runs at a decent rate and yet does not dominate the system.