📄 ke_x.h
字号:
WaitBlock->NextWaitBlock = WaitBlockArray; \
\
/* Set default wait status */ \
Thread->WaitStatus = STATUS_WAIT_0; \
\
/* Check if we have a timer */ \
if (Timeout) \
{ \
/* Link to the block */ \
TimerBlock->NextWaitBlock = WaitBlockArray; \
\
/* Setup the timer */ \
KxSetTimerForThreadWait(Timer, *Timeout, &Hand); \
\
/* Save the due time for the caller */ \
DueTime.QuadPart = Timer->DueTime.QuadPart; \
\
/* Initialize the list */ \
InitializeListHead(&Timer->Header.WaitListHead); \
} \
\
/* Set wait settings */ \
Thread->Alertable = Alertable; \
Thread->WaitMode = WaitMode; \
Thread->WaitReason = WaitReason; \
\
/* Check if we can swap the thread's stack */ \
Thread->WaitListEntry.Flink = NULL; \
Swappable = KiCheckThreadStackSwap(Thread, WaitMode); \
\
/* Set the wait time */ \
Thread->WaitTime = KeTickCount.LowPart;
#define KxSingleThreadWait() \
/* Setup the Wait Block */ \
Thread->WaitBlockList = WaitBlock; \
WaitBlock->WaitKey = STATUS_SUCCESS; \
WaitBlock->Object = Object; \
WaitBlock->WaitType = WaitAny; \
\
/* Clear wait status */ \
Thread->WaitStatus = STATUS_SUCCESS; \
\
/* Check if we have a timer */ \
if (Timeout) \
{ \
/* Setup the timer */ \
KxSetTimerForThreadWait(Timer, *Timeout, &Hand); \
\
/* Save the due time for the caller */ \
DueTime.QuadPart = Timer->DueTime.QuadPart; \
\
/* Pointer to timer block */ \
WaitBlock->NextWaitBlock = TimerBlock; \
TimerBlock->NextWaitBlock = WaitBlock; \
\
/* Link the timer to this Wait Block */ \
Timer->Header.WaitListHead.Flink = &TimerBlock->WaitListEntry; \
Timer->Header.WaitListHead.Blink = &TimerBlock->WaitListEntry; \
} \
else \
{ \
/* No timer block, just ourselves */ \
WaitBlock->NextWaitBlock = WaitBlock; \
} \
\
/* Set wait settings */ \
Thread->Alertable = Alertable; \
Thread->WaitMode = WaitMode; \
Thread->WaitReason = WaitReason; \
\
/* Check if we can swap the thread's stack */ \
Thread->WaitListEntry.Flink = NULL; \
Swappable = KiCheckThreadStackSwap(Thread, WaitMode); \
\
/* Set the wait time */ \
Thread->WaitTime = KeTickCount.LowPart;
#define KxQueueThreadWait() \
/* Setup the Wait Block */ \
Thread->WaitBlockList = WaitBlock; \
WaitBlock->WaitKey = STATUS_SUCCESS; \
WaitBlock->Object = Queue; \
WaitBlock->WaitType = WaitAny; \
WaitBlock->Thread = Thread; \
\
/* Clear wait status */ \
Thread->WaitStatus = STATUS_SUCCESS; \
\
/* Check if we have a timer */ \
if (Timeout) \
{ \
/* Setup the timer */ \
KxSetTimerForThreadWait(Timer, *Timeout, &Hand); \
\
/* Save the due time for the caller */ \
DueTime.QuadPart = Timer->DueTime.QuadPart; \
\
/* Pointer to timer block */ \
WaitBlock->NextWaitBlock = TimerBlock; \
TimerBlock->NextWaitBlock = WaitBlock; \
\
/* Link the timer to this Wait Block */ \
Timer->Header.WaitListHead.Flink = &TimerBlock->WaitListEntry; \
Timer->Header.WaitListHead.Blink = &TimerBlock->WaitListEntry; \
} \
else \
{ \
/* No timer block, just ourselves */ \
WaitBlock->NextWaitBlock = WaitBlock; \
} \
\
/* Set wait settings */ \
Thread->Alertable = FALSE; \
Thread->WaitMode = WaitMode; \
Thread->WaitReason = WrQueue; \
\
/* Check if we can swap the thread's stack */ \
Thread->WaitListEntry.Flink = NULL; \
Swappable = KiCheckThreadStackSwap(Thread, WaitMode); \
\
/* Set the wait time */ \
Thread->WaitTime = KeTickCount.LowPart;
//
// Unwaits a Thread
//
FORCEINLINE
VOID
KxUnwaitThread(IN DISPATCHER_HEADER *Object,
IN KPRIORITY Increment)
{
PLIST_ENTRY WaitEntry, WaitList;
PKWAIT_BLOCK WaitBlock;
PKTHREAD WaitThread;
ULONG WaitKey;
/* Loop the Wait Entries */
WaitList = &Object->WaitListHead;
ASSERT(IsListEmpty(&Object->WaitListHead) == FALSE);
WaitEntry = WaitList->Flink;
do
{
/* Get the current wait block */
WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
/* Get the waiting thread */
WaitThread = WaitBlock->Thread;
/* Check the current Wait Mode */
if (WaitBlock->WaitType == WaitAny)
{
/* Use the actual wait key */
WaitKey = WaitBlock->WaitKey;
}
else
{
/* Otherwise, use STATUS_KERNEL_APC */
WaitKey = STATUS_KERNEL_APC;
}
/* Unwait the thread */
KiUnwaitThread(WaitThread, WaitKey, Increment);
/* Next entry */
WaitEntry = WaitList->Flink;
} while (WaitEntry != WaitList);
}
//
// Unwaits a Thread waiting on an event
//
FORCEINLINE
VOID
KxUnwaitThreadForEvent(IN PKEVENT Event,
IN KPRIORITY Increment)
{
PLIST_ENTRY WaitEntry, WaitList;
PKWAIT_BLOCK WaitBlock;
PKTHREAD WaitThread;
/* Loop the Wait Entries */
WaitList = &Event->Header.WaitListHead;
ASSERT(IsListEmpty(&Event->Header.WaitListHead) == FALSE);
WaitEntry = WaitList->Flink;
do
{
/* Get the current wait block */
WaitBlock = CONTAINING_RECORD(WaitEntry, KWAIT_BLOCK, WaitListEntry);
/* Get the waiting thread */
WaitThread = WaitBlock->Thread;
/* Check the current Wait Mode */
if (WaitBlock->WaitType == WaitAny)
{
/* Un-signal it */
Event->Header.SignalState = 0;
/* Un-signal the event and unwait the thread */
KiUnwaitThread(WaitThread, WaitBlock->WaitKey, Increment);
break;
}
/* Unwait the thread with STATUS_KERNEL_APC */
KiUnwaitThread(WaitThread, STATUS_KERNEL_APC, Increment);
/* Next entry */
WaitEntry = WaitList->Flink;
} while (WaitEntry != WaitList);
}
//
// This routine queues a thread that is ready on the PRCB's ready lists.
// If this thread cannot currently run on this CPU, then the thread is
// added to the deferred ready list instead.
//
// This routine must be entered with the PRCB lock held and it will exit
// with the PRCB lock released!
//
FORCEINLINE
VOID
KxQueueReadyThread(IN PKTHREAD Thread,
IN PKPRCB Prcb)
{
BOOLEAN Preempted;
KPRIORITY Priority;
/* Sanity checks */
ASSERT(Prcb == KeGetCurrentPrcb());
ASSERT(Thread->State == Running);
ASSERT(Thread->NextProcessor == Prcb->Number);
/* Check if this thread is allowed to run in this CPU */
#ifdef _CONFIG_SMP
if ((Thread->Affinity) & (Prcb->SetMember))
#else
if (TRUE)
#endif
{
/* Set thread ready for execution */
Thread->State = Ready;
/* Save current priority and if someone had pre-empted it */
Priority = Thread->Priority;
Preempted = Thread->Preempted;
/* We're not pre-empting now, and set the wait time */
Thread->Preempted = FALSE;
Thread->WaitTime = KeTickCount.LowPart;
/* Sanity check */
ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));
/* Insert this thread in the appropriate order */
Preempted ? InsertHeadList(&Prcb->DispatcherReadyListHead[Priority],
&Thread->WaitListEntry) :
InsertTailList(&Prcb->DispatcherReadyListHead[Priority],
&Thread->WaitListEntry);
/* Update the ready summary */
Prcb->ReadySummary |= PRIORITY_MASK(Priority);
/* Sanity check */
ASSERT(Priority == Thread->Priority);
/* Release the PRCB lock */
KiReleasePrcbLock(Prcb);
}
else
{
/* Otherwise, prepare this thread to be deferred */
Thread->State = DeferredReady;
Thread->DeferredProcessor = Prcb->Number;
/* Release the lock and defer scheduling */
KiReleasePrcbLock(Prcb);
KiDeferredReadyThread(Thread);
}
}
//
// This routine scans for an appropriate ready thread to select at the
// given priority and for the given CPU.
//
FORCEINLINE
PKTHREAD
KiSelectReadyThread(IN KPRIORITY Priority,
IN PKPRCB Prcb)
{
ULONG PrioritySet, HighPriority;
PLIST_ENTRY ListEntry;
PKTHREAD Thread = NULL;
/* Save the current mask and get the priority set for the CPU */
PrioritySet = Prcb->ReadySummary >> Priority;
if (!PrioritySet) goto Quickie;
/* Get the highest priority possible */
BitScanReverse((PULONG)&HighPriority, PrioritySet);
ASSERT((PrioritySet & PRIORITY_MASK(HighPriority)) != 0);
HighPriority += Priority;
/* Make sure the list isn't empty at the highest priority */
ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[HighPriority]) == FALSE);
/* Get the first thread on the list */
ListEntry = Prcb->DispatcherReadyListHead[HighPriority].Flink;
Thread = CONTAINING_RECORD(ListEntry, KTHREAD, WaitListEntry);
/* Make sure this thread is here for a reason */
ASSERT(HighPriority == Thread->Priority);
ASSERT(Thread->Affinity & AFFINITY_MASK(Prcb->Number));
ASSERT(Thread->NextProcessor == Prcb->Number);
/* Remove it from the list */
if (RemoveEntryList(&Thread->WaitListEntry))
{
/* The list is empty now, reset the ready summary */
Prcb->ReadySummary ^= PRIORITY_MASK(HighPriority);
}
/* Sanity check and return the thread */
Quickie:
ASSERT((Thread == NULL) ||
(Thread->BasePriority == 0) ||
(Thread->Priority != 0));
return Thread;
}
//
// This routine computes the new priority for a thread. It is only valid for
// threads with priorities in the dynamic priority range.
//
SCHAR
FORCEINLINE
KiComputeNewPriority(IN PKTHREAD Thread,
IN SCHAR Adjustment)
{
SCHAR Priority;
/* Priority sanity checks */
ASSERT((Thread->PriorityDecrement >= 0) &&
(Thread->PriorityDecrement <= Thread->Priority));
ASSERT((Thread->Priority < LOW_REALTIME_PRIORITY) ?
TRUE : (Thread->PriorityDecrement == 0));
/* Get the current priority */
Priority = Thread->Priority;
if (Priority < LOW_REALTIME_PRIORITY)
{
/* Decrease priority by the priority decrement */
Priority -= (Thread->PriorityDecrement + Adjustment);
/* Don't go out of bounds */
if (Priority < Thread->BasePriority) Priority = Thread->BasePriority;
/* Reset the priority decrement */
Thread->PriorityDecrement = 0;
}
/* Sanity check */
ASSERT((Thread->BasePriority == 0) || (Priority != 0));
/* Return the new priority */
return Priority;
}
PRKTHREAD
FORCEINLINE
KeGetCurrentThread(VOID)
{
/* Return the current thread */
return ((PKIPCR)KeGetPcr())->PrcbData.CurrentThread;
}
UCHAR
FORCEINLINE
KeGetPreviousMode(VOID)
{
/* Return the current mode */
return KeGetCurrentThread()->PreviousMode;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -