怎么样从一个延迟就绪队列里选择合适的线程运行呢?下面就来分析这段代码,如下:
#001 //
#002 // This routine scans for an appropriate ready thread to select at the
#003 // given priority and for the given CPU.
#004 //
#005 FORCEINLINE
#006 PKTHREAD
#007 KiSelectReadyThread(IN KPRIORITY Priority,
#008 IN PKPRCB Prcb)
#009 {
#010 ULONG PrioritySet;
#011 LONG HighPriority;
#012 PLIST_ENTRY ListEntry;
#013 PKTHREAD Thread = NULL;
#014
获取当前处理器的优先级。
#015 /* Save the current mask and get the priority set for the CPU */
#016 PrioritySet = Prcb->ReadySummary >> Priority;
#017 if (!PrioritySet) goto Quickie;
#018
计算合适的优先级。
#019 /* Get the highest priority possible */
#020 BitScanReverse((PULONG)&HighPriority, PrioritySet);
#021 ASSERT((PrioritySet & PRIORITY_MASK(HighPriority)) != 0);
#022 HighPriority += Priority;
#023
#024 /* Make sure the list isn't empty at the highest priority */
#025 ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[HighPriority]) == FALSE);
#026
从给出的优先级队列里找到合适的就绪线程。
#027 /* Get the first thread on the list */
#028 ListEntry = Prcb->DispatcherReadyListHead[HighPriority].Flink;
#029 Thread = CONTAINING_RECORD(ListEntry, KTHREAD, WaitListEntry);
#030
#031 /* Make sure this thread is here for a reason */
#032 ASSERT(HighPriority == Thread->Priority);
#033 ASSERT(Thread->Affinity & AFFINITY_MASK(Prcb->Number));
#034 ASSERT(Thread->NextProcessor == Prcb->Number);
#035
删除就绪队列里的线程。
#036 /* Remove it from the list */
#037 if (RemoveEntryList(&Thread->WaitListEntry))
#038 {
#039 /* The list is empty now, reset the ready summary */
#040 Prcb->ReadySummary ^= PRIORITY_MASK(HighPriority);
#041 }
#042
#043 /* Sanity check and return the thread */
#044 Quickie:
#045 ASSERT((Thread == NULL) ||
#046 (Thread->BasePriority == 0) ||
#047 (Thread->Priority != 0));
#048 return Thread;
#049 }
通过上面函数处理,就可以从合适的优先级队列里得到下一个运行的线程。