reactos操作系统实现(43)
前面介绍放到延迟队列是单核的版本,下面来学习多核的版本,代码如下: #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函数处理了插入线程和当前处理器、队列线程的比较优先级,以便设置为合适地方运行,或者放到队列里合适位置。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |