Thread Scheduling
====================
Windows has implemented a priority-driven preemptible scheduling system-the highest-priority running thread will continue to run, and the thread can only run on certain processors that allow it to run, this phenomenon is called processor affinity. by default, threads can run on any available processor. However, you can use the Windows scheduling function to set affinity mask in the image header to modify processor affinity.
When a thread is selected for running, it runs for a period of time, which is called quantum (quota ). quantum is like this for a while. Windows allows the thread to run first. After this time, Windows can interrupt the thread to do other things, this includes determining whether a thread with the same priority or higher priority as the current thread is waiting, and determining whether the priority of the current thread needs to be lowered. the quantum value varies among different threads, even when the operating system is different. however, a thread may not complete its quantum. because sched is implemented in windows, if another thread has a higher priority, when it is ready to run, the currently running iancheng may be killed before the end of his time slice. in fact, the thread can even be determined to run later before starting his quantum, And the CPU is snatched away.
The thread scheduling code of Windows is implemented in the kernel. no scheduler module or function exists, and the scheduling code is scattered in the processing of scheduling related events in the kernel. these functions are called Kernel schedulers (kernel's dispatcher ). thread allocation occurs at the DPC/dispatch level and is triggered by any of the following events.
- A thread enters the executable state (ready to execute). For example, a thread has just been created or released from the waiting state.
- The thread is out of the running state because its quantum is finished, terminate, or wait.
- The thread priority has changed, either because the system service calls or because Windows has modified the priority value.
- Processor affinity modified
In any case, windows must determine the next thread to run. when Widnows selects a new thread for running, it executes context switch (context conversion ). context conversion is a process in which unstable machine States related to running threads are stored, the statuses of other threads are loaded, and execution of new threads starts.
Obviously, Windows allocates resources at the thread granularity. the concept of a process is a non-running unit. It only provides context and resources for its threads, and such a scheduling arrangement conforms to this concept. because the scheduling is strictly based on the thread, you do not need to consider which process the thread belongs to during scheduling. for example, process a has 10 runnable threads and process B has two. All 12 threads have the same priority, and each thread is allocated a CPU time of 1/12, instead of giving a 50% or B 50%.
Interrupt priority vs process priority
======================================
As mentioned above, the thread usually runs on IRQL 0 or 1. Windows debugging 3 introduces IRQL information.
The user-state thread is always running on irql0, that is, the lowest level. Even if it is not interrupted, it can be said that there is no level. Any interruption can interrupt the execution of the User-state thread, any user-state thread, no matter how high its priority is, cannot interfere with hardware interruption.
Only the kernel state APC is executed on the irql1 level, because they can interrupt user State threads at will.
A kernel-running thread can improve its IRQL level for some special processing, for example, when executing a system call involving thread allocation (IRQL 2 ).
Thread status
========================
The details are as follows:
- Ready --- when dispatcher is looking for a thread for execution, it only considers the threads in ready state in the thread pool. They are only waiting for execution.
- Standby --- a thread in the STANDBY state has been selected by a processor as the next object to be processed. when the correct conditions are met, dispatcher executes context conversion for this thread. for each processor in the system, only one thread can be in the STANDBY state.
- Running --- once the dispatcher executes context conversion for a thread, the thread enters the running state. the thread continues until the following conditions occur. the kernel preemptible the resource so that it can be used by threads of a higher level. 2. his quantum is over. 3. it stops running (terminate ). 4. the thread voluntarily enters the waiting state.
- Waiting --- a thread enters the waiting state through the following ways: 1. voluntarily enters the waiting state and waits for an object to synchronize its execution. 2. the operating system (such as the IO system) or Environment Subsystem guides the thread to suspend itself. when the thread waits for the end, check its priority to determine whether the thread is in the running or ready status.
- Transition --- when the thread is ready and can be executed, it happens that the memory page of the kernel stack is swapped out of the memory and the thread enters the transition state. when the kernel stack is brought back to the memory, the thread enters the ready state.
- Terminated --- when a thread finishes execution, it enters a terminated state ). once it is over, the thread object may be deleted, maybe not (the object manager will set this policy ).
- Initialized --- the state of internal use (used internally) when the thread is created)
Quota (quantum)
================================
Quantum is a thread running period of time. After this period, the operating system checks whether there are other threads with the same priority need to enter the running state. if a thread completes its quantum and no other thread has the same priority as it, Windows will reassign it to the thread a quantum.
Each thread has a quantum value, which indicates how long the thread can run before the quantum expires. this value is not the length of time, but an integer value. We call it quantum units.
Quota Calculation
------------------------
When the thread is started, Windows XP and Windows 2000 Professional default quantum values are 6. the ultimate goal is to minimize the context switching time. with a longer quantum, the server application has a better chance to complete the request sent from the client, and returns to the waiting state before the quota ends. the default quantum value of Windows Server 2003 is 36, while that of Windows Server 2000 is 12.
At any time of clock interruption, the clock interruption handler deducts a value from quantum in the county seat. 3. if the quantum of the thread is no longer available, the processing program with the thread quota used up is activated, and another thread may be selected to run. because 3 is deducted for every clock interruption, each thread runs two clock cycles (XP) by default ).
Even if the system is at a DPC/dispatch level or higher (for example, when a DPC or a terminal service program is executing), when the clock is interrupted, even if the thread has not completed a whole clock cycle, the current thread will still reduce its quantum. if the quantum reduction action is not completed, the device will be interrupted; or the DPC may never reduce its quantum until the timer in the clock cycle is interrupted.
The clock cycle length varies depending on the hardware system platform. the frequency of clock interruption depends on Hal, not the kernel. for example, the clock cycle of most x86 single processors is 10 milliseconds, while that of multi-processor x86 platforms is 15 milliseconds.
The clock tick, we use three quantum to express it, instead of one reason, this allows quantum to decline part of it while waiting for the end. when a thread has a base priority of less than 14 and executes the wait function (WaitforsingleobjectOrWaitformultipleobjects), His quantum reduces the unit of 1 quantum (threads with a higher priority than 14 or 14 will reset their priority reset after the end ).
Such a reduction solves the following situation: a thread enters the waiting state before the clock timer is triggered. if there is no adjustment, he may never reduce his quantum. for example, a thread is running, enters the waiting state, and then runs again, but does not belong to the currently running thread whenever the clock timer is triggered, therefore, the quantum of this thread will never be reduced.
Voluntary Conversion
==================
Scenario
In Windows, the question "Who should get the CPU" depends on the thread priority. But how does this happen in actual operation? The following sections describe in detail how the preemptible multi-task system works at the Thread level.
Voluntary Conversion
First, a thread can voluntarily stop using the processor by waiting for an object. for example, event, mutex, flag signal, Io completion port, process, thread, window message, etc. you can wait for an object by calling some Win32 functions, suchWaitforsingleobjectOrWaitformultipleObjects
Voluntary conversion is roughly equivalent to a course that has not been prepared by a thread in front of the dining table. rather than serving as a ordering team, we can stand aside and let other threads execute their requests when the chefs cook their burgers. when Hamburg is ready, the first thread is placed at the end of the ready team with the same priority as it. in any case, most pending operations will lead to a temporary increase in priority, so that the thread can quickly take it away and start eating after its hamburger is ready.
The top thread voluntarily gave up the processor, so the thread in the next ready queue (the block with an aperture on the head) can run. although the figure shows that the priority of the thread voluntarily abandoned is reduced, it does not. it is only moved to the waiting queue. what about the remaining quantum of this thread? The quantum value is not reset when it enters the waiting state. In fact, as mentioned earlier, when the waiting state is satisfied, the thread's quantum will reduce the unit of quantum, equal to 1/3 of a clock cycle (except for threads with a priority of 14 or above, their quantum will be reset after waiting .)
Preemption
======================
In this scenario, a low-level thread is snatched from the CPU by a high-level thread that just enters the ready state. This may happen for the following reasons:
1. The thread with a higher priority is finished. (This event occurs when other threads have waited)
2. The priority of a thread should not be increased or decreased.
Any one of the two can lead to a high-priority thread to seize the CPU.
Note: The threads running in the kernel state can be preemptible by the user State threads. Whether the threads are running in the kernel state has nothing to do with preemption. The thread priority is an indicator determined by the preemption.
When a thread is preemptible, it is placed in the header of the ready queue of its priority, so that when it runs again, it can end its quantum.
A thread with a priority of 18 has recovered from the waiting state and re-acquired the CPU, causing a thread with a priority of 16 to be hit in the ready queue. Note that this is the first line, instead of the team end.
Quota ended
======================================
When a thread uses up its CPU time slice quota, windows must decide whether to reduce the priority of the thread and whether another thread should be scheduled to the processor.
If the thread priority is reduced, Windows looks for a more appropriate thread to arrange. (for example, a more suitable thread should be in the ready queue and have a higher priority than the new priority of the currently running thread ). if the thread priority is not reduced, Widnows selects the next thread in the ready queue and places the previous thread to the end of the queue (give it a new quantum, modify its status to ready ). such a situation is shown in. if no other thread with the same priority is in ready state, then the current thread will run another quantum.
In fact, the fact that a thread has quantum does not mean that it must end the quantum. A thread may voluntarily give up CPU usage before the end of his time slice, either it enters the waiting state, or it is hit by a higher-priority thread to the head of the ready queue. as discussed above, if you voluntarily give up CPU control, the thread will be allocated a new quantum value when it runs again. if a thread is preemptible, it is moved to the head of the corresponding priority ready queue. Later, when it is scheduled, the thread will run until the time slice ends.