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运行,也就是0CPU

#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函数处理了插入线程和当前处理器、队列线程的比较优先级,以便设置为合适地方运行,或者放到队列里合适位置。

你可能感兴趣的:(reactos操作系统实现(43))