前面介绍放到延迟队列是单核的版本,下面来学习多核的版本,代码如下:
#001 //
#002 // This routine makes the thread deferred ready on the boot CPU.
#003 //
#004 FORCEINLINE
#005 VOID
#006 KiInsertDeferredReadyList(IN PKTHREAD Thread)
#007 {
设置线程状态和运行线程的CPU。
#008 /* Set the thread to deferred state and boot CPU */
#009 Thread->State = DeferredReady;
#010 Thread->DeferredProcessor = 0;
#011
立即把线程放到延迟就绪队列。
#012 /* Make the thread ready immediately */
#013 KiDeferredReadyThread(Thread);
#014 }
从上面的函数可以看到,调用函数KiDeferredReadyThread来放到延迟就绪队列。它的代码如下:
#001 VOID
#002 NTAPI
#003 KiDeferredReadyThread(IN PKTHREAD Thread)
#004 {
#005 PKPRCB Prcb;
#006 BOOLEAN Preempted;
#007 ULONG Processor = 0;
#008 KPRIORITY OldPriority;
#009 PKTHREAD NextThread;
#010
#011 /* Sanity checks */
#012 ASSERT(Thread->State == DeferredReady);
#013 ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY));
#014
检查线程是否需要调整优先级。
#015 /* Check if we have any adjusts to do */
#016 if (Thread->AdjustReason == AdjustBoost)
#017 {
锁住线程,以便修改线程的数据。
#018 /* Lock the thread */
#019 KiAcquireThreadLock(Thread);
#020
检查线程是否可以提高优先级。
#021 /* Check if the priority is low enough to qualify for boosting */
#022 if ((Thread->Priority <= Thread->AdjustIncrement) &&
#023 (Thread->Priority < (LOW_REALTIME_PRIORITY - 3)) &&
#024 !(Thread->DisableBoost))
#025 {
计算可以设置最高的优先级。
#026 /* Calculate the new priority based on the adjust increment */
#027 OldPriority = min(Thread->AdjustIncrement + 1,
#028 LOW_REALTIME_PRIORITY - 3);
#029
测试优先级是否在可以设置的范围。
#030 /* Make sure we're not decreasing outside of the priority range */
#031 ASSERT((Thread->PriorityDecrement >= 0) &&
#032 (Thread->PriorityDecrement <= Thread->Priority));
#033
计算可以减少的最大优先级数。
#034 /* Calculate the new priority decrement based on the boost */
#035 Thread->PriorityDecrement += ((SCHAR)OldPriority - Thread->Priority);
#036
测试减少的优先级是否有效。
#037 /* Again verify that this decrement is valid */
#038 ASSERT((Thread->PriorityDecrement >= 0) &&
#039 (Thread->PriorityDecrement <= OldPriority));
#040
设置最新的优先级。
#041 /* Set the new priority */
#042 Thread->Priority = (SCHAR)OldPriority;
#043 }
#044
设置线程获取的时间片。
#045 /* We need 4 quanta, make sure we have them, then decrease by one */
#046 if (Thread->Quantum < 4) Thread->Quantum = 4;
#047 Thread->Quantum--;
#048
#049 /* Make sure the priority is still valid */
#050 ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY));
#051
释放线程锁。
#052 /* Release the lock and clear the adjust reason */
#053 KiReleaseThreadLock(Thread);
#054 Thread->AdjustReason = AdjustNone;
#055 }
#056 else if (Thread->AdjustReason == AdjustUnwait)
#057 {
检查线程是否为实时优先线程。
#058 /* Acquire the thread lock and check if this is a real-time thread */
#059 KiAcquireThreadLock(Thread);
#060 if (Thread->Priority < LOW_REALTIME_PRIORITY)
#061 {
它不是实时优先线程,判断线程是否为临界线程。
#062 /* It's not real time, but is it time critical? */
#063 if (Thread->BasePriority >= (LOW_REALTIME_PRIORITY - 2))
#064 {
是否为可变实时优先级。
#065 /* It is, so simply reset its quantum */
#066 Thread->Quantum = Thread->QuantumReset;
#067 }
#068 else
#069 {
前面已经自动调整过优先级。
#070 /* Has the priority been adjusted previously? */
#071 if (!(Thread->PriorityDecrement) && (Thread->AdjustIncrement))
#072 {
#073 /* Yes, reset its quantum */
#074 Thread->Quantum = Thread->QuantumReset;
#075 }
#076
计算最新的优先级。
#077 /* Wait code already handles quantum adjustment during APCs */
#078 if (Thread->WaitStatus != STATUS_KERNEL_APC)
#079 {
#080 /* Decrease the quantum by one and check if we're out */
#081 if (--Thread->Quantum <= 0)
#082 {
#083 /* We are, reset the quantum and get a new priority */
#084 Thread->Quantum = Thread->QuantumReset;
#085 Thread->Priority = KiComputeNewPriority(Thread, 1);
#086 }
#087 }
#088 }
#089
检查是否需要调整优先级。
#090 /* Now check if we have no decrement and boosts are enabled */
#091 if (!(Thread->PriorityDecrement) && !(Thread->DisableBoost))
#092 {
#093 /* Make sure we have an increment */
#094 ASSERT(Thread->AdjustIncrement >= 0);
#095
#096 /* Calculate the new priority after the increment */
#097 OldPriority = Thread->BasePriority + Thread->AdjustIncrement;
#098
#099 /* Check if this new priority is higher */
#100 if (OldPriority > Thread->Priority)
#101 {
#102 /* Make sure we don't go into the real time range */
#103 if (OldPriority >= LOW_REALTIME_PRIORITY)
#104 {
#105 /* Normalize it back down one notch */
#106 OldPriority = LOW_REALTIME_PRIORITY - 1;
#107 }
#108
#109 /* Check if the priority is higher then the boosted base */
#110 if (OldPriority > (Thread->BasePriority +
#111 Thread->AdjustIncrement))
#112 {
#113 /* Setup a priority decrement to nullify the boost */
#114 Thread->PriorityDecrement = ((SCHAR)OldPriority -
#115 Thread->BasePriority -
#116 Thread->AdjustIncrement);
#117 }
#118
#119 /* Make sure that the priority decrement is valid */
#120 ASSERT((Thread->PriorityDecrement >= 0) &&
#121 (Thread->PriorityDecrement <= OldPriority));
#122
#123 /* Set this new priority */
#124 Thread->Priority = (SCHAR)OldPriority;
#125 }
#126 }
#127 }
#128 else
#129 {
线程是实时优先级。
#130 /* It's a real-time thread, so just reset its quantum */
#131 Thread->Quantum = Thread->QuantumReset;
#132 }
#133
#134 /* Make sure the priority makes sense */
#135 ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY));
#136
#137 /* Release the thread lock and reset the adjust reason */
#138 KiReleaseThreadLock(Thread);
#139 Thread->AdjustReason = AdjustNone;
#140 }
#141
清除线程的preemption状态和保存当前值。
#142 /* Clear thread preemption status and save current values */
#143 Preempted = Thread->Preempted;
#144 OldPriority = Thread->Priority;
#145 Thread->Preempted = FALSE;
#146
设置线程为引导CPU运行,也就是0号CPU。
#147 /* Queue the thread on CPU 0 and get the PRCB */
#148 Thread->NextProcessor = 0;
#149 Prcb = KiProcessorBlock[0];
#150
检查当前处理器是否为空闲状态,如果为空闲状态,就设置为下一个运行的线程。
#151 /* Check if we have an idle summary */
#152 if (KiIdleSummary)
#153 {
#154 /* Clear it and set this thread as the next one */
#155 KiIdleSummary = 0;
#156 Thread->State = Standby;
#157 Prcb->NextThread = Thread;
#158 return;
#159 }
#160
设置线程下一个运行的CPU编号。
#161 /* Set the CPU number */
#162 Thread->NextProcessor = (UCHAR)Processor;
#163
获取下一个准备调度的线程。
#164 /* Get the next scheduled thread */
#165 NextThread = Prcb->NextThread;
#166 if (NextThread)
#167 {
#168 /* Sanity check */
#169 ASSERT(NextThread->State == Standby);
#170
如果当前线程的优先级大于队列中准备运行的线程,那么当前线程设置为运行状态,下一个线程重新计算运行状态。
#171 /* Check if priority changed */
#172 if (OldPriority > NextThread->Priority)
#173 {
#174 /* Preempt the thread */
#175 NextThread->Preempted = TRUE;
#176
#177 /* Put this one as the next one */
#178 Thread->State = Standby;
#179 Prcb->NextThread = Thread;
#180
#181 /* Set it in deferred ready mode */
#182 NextThread->State = DeferredReady;
#183 NextThread->DeferredProcessor = Prcb->Number;
#184 KiReleasePrcbLock(Prcb);
#185 KiDeferredReadyThread(NextThread);
#186 return;
#187 }
#188 }
#189 else
#190 {
如果队列里没有就绪线程,就把当前线程设置为就绪线程。
#191 /* Set the next thread as the current thread */
#192 NextThread = Prcb->CurrentThread;
#193 if (OldPriority > NextThread->Priority)
#194 {
#195 /* Preempt it if it's already running */
#196 if (NextThread->State == Running) NextThread->Preempted = TRUE;
#197
#198 /* Set the thread on standby and as the next thread */
#199 Thread->State = Standby;
#200 Prcb->NextThread = Thread;
#201
#202 /* Release the lock */
#203 KiReleasePrcbLock(Prcb);
#204
#205 /* Check if we're running on another CPU */
#206 if (KeGetCurrentProcessorNumber() != Thread->NextProcessor)
#207 {
#208 /* We are, send an IPI */
#209 KiIpiSend(AFFINITY_MASK(Thread->NextProcessor), IPI_DPC);
#210 }
#211 return;
#212 }
#213 }
#214
#215 /* Sanity check */
#216 ASSERT((OldPriority >= 0) && (OldPriority <= HIGH_PRIORITY));
#217
设置线程为准备好状态。
#218 /* Set this thread as ready */
#219 Thread->State = Ready;
#220 Thread->WaitTime = KeTickCount.LowPart;
#221
把线程插入到队列里合适的位置。
#222 /* Insert this thread in the appropriate order */
#223 Preempted ? InsertHeadList(&Prcb->DispatcherReadyListHead[OldPriority],
#224 &Thread->WaitListEntry) :
#225 InsertTailList(&Prcb->DispatcherReadyListHead[OldPriority],
#226 &Thread->WaitListEntry);
#227
更新当前处理器优先级别。
#228 /* Update the ready summary */
#229 Prcb->ReadySummary |= PRIORITY_MASK(OldPriority);
#230
#231 /* Sanity check */
#232 ASSERT(OldPriority == Thread->Priority);
#233
#234 /* Release the lock */
#235 KiReleasePrcbLock(Prcb);
#236 }
KiDeferredReadyThread函数处理了插入线程和当前处理器、队列线程的比较优先级,以便设置为合适地方运行,或者放到队列里合适位置。