Windows优先级调度算法
系统维护了一个全局的处理器数组KiProcessorBlock,其中每个元素对应于一个处理器的KPRCB对象。其次,另有一个全局变量KiIdleSummary记录了哪些处理器当前是空闲的。所谓一个处理器是空闲的,是指该处理器正在执行空闲循环。KiIdleSummary每一位对应于一个处理器,在32位系统中,由于KiIdleSummary是32位的。所以只支持至多32个处理器。
当一个处理器没有找到合适的线程运行时,会调用KiSetIdleSummary函数来设置KiIdleSummary中相应位,相反,如果一个空闲处理器被分配了一个线程来运行,则需要通过调用KiClearIdleSummary函数来清除KiIdleSummary中相应位。
在每个处理器的KPRCB结构中,都有一个单链表DeferredReadyListHead记录了那些在该处理器上处于延迟就绪状态的线程,以及一个双链表数组DispatcherReadyListHead记录了在每个优先级上已经被分配到此处理器上的就绪状态的线程。另有一个32位摘要位码ReadySummary反映了哪些优先级的就绪链表是非空的,所以,KiSelectReadyThread和KiFindReadyThread函数利用链表数组和摘要位码信息,能很快地找到满足条件地线程。
当一个线程进入等待状态时,会调用KeDelayExecutionThread,KeWaitForSingleObject或KeWaitForMultipleObjects函数,若等待条件未满足,则线程会放弃当前处理器。其次,一个线程在执行过程中由于系统的某些原因,不得不放弃对于当前处理器的执行权,比如一个线程用完了它的当前时限时,只要还存在优先级大于等于它的其他线程,那么它就必须交出处理器的执行权。分为自愿放弃执行权和被迫放弃执行权。
自愿放弃执行权
调用KiSwapThread函数,当前线程自愿把控制权交给线程调度器,然后通过KiSwapContext来完成线程切换
线程自愿进入等待状态,即KeDelayExecutionThread,KeWaitForSingleObject和KeWaitForMultipleObject函数
线程进入门等待状态,发生在KeWaitForGate函数中
在队列对象中,如果一个线程调用KeRemoveQueue,但又不能马上获得队列中的项,该线程也会进入等待状态,并且调用KiSwapThread函数把控制权交给线程调度器
当一个线程attach到一个进程的地址空间时,若目标进程还没有换入内存,尽管当前线程是就绪的,但是它不能继续执行,所以调用KiSwapThread函数把控制权交给线程调度器
被迫放弃执行权
时限用完
被抢占