📄 ke_x.h
字号:
/* We must be at DPC level, acquire the lock safely */
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
KeAcquireInStackQueuedSpinLockAtDpcLevel(&DeviceQueue->Lock,
DeviceLock);
}
}
FORCEINLINE
VOID
KiReleaseDeviceQueueLock(IN PKLOCK_QUEUE_HANDLE DeviceLock)
{
/* Check if we were called from a threaded DPC */
if (KeGetCurrentPrcb()->DpcThreadActive)
{
/* Unlock the Queue, we're not at DPC level */
KeReleaseInStackQueuedSpinLock(DeviceLock);
}
else
{
/* We must be at DPC level, release the lock safely */
ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
KeReleaseInStackQueuedSpinLockFromDpcLevel(DeviceLock);
}
}
//
// Satisfies the wait of any dispatcher object
//
#define KiSatisfyObjectWait(Object, Thread) \
{ \
/* Special case for Mutants */ \
if ((Object)->Header.Type == MutantObject) \
{ \
/* Decrease the Signal State */ \
(Object)->Header.SignalState--; \
\
/* Check if it's now non-signaled */ \
if (!(Object)->Header.SignalState) \
{ \
/* Set the Owner Thread */ \
(Object)->OwnerThread = Thread; \
\
/* Disable APCs if needed */ \
Thread->KernelApcDisable = Thread->KernelApcDisable - \
(Object)->ApcDisable; \
\
/* Check if it's abandoned */ \
if ((Object)->Abandoned) \
{ \
/* Unabandon it */ \
(Object)->Abandoned = FALSE; \
\
/* Return Status */ \
Thread->WaitStatus = STATUS_ABANDONED; \
} \
\
/* Insert it into the Mutant List */ \
InsertHeadList(Thread->MutantListHead.Blink, \
&(Object)->MutantListEntry); \
} \
} \
else if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
EventSynchronizationObject) \
{ \
/* Synchronization Timers and Events just get un-signaled */ \
(Object)->Header.SignalState = 0; \
} \
else if ((Object)->Header.Type == SemaphoreObject) \
{ \
/* These ones can have multiple states, so we only decrease it */ \
(Object)->Header.SignalState--; \
} \
}
//
// Satisfies the wait of a mutant dispatcher object
//
#define KiSatisfyMutantWait(Object, Thread) \
{ \
/* Decrease the Signal State */ \
(Object)->Header.SignalState--; \
\
/* Check if it's now non-signaled */ \
if (!(Object)->Header.SignalState) \
{ \
/* Set the Owner Thread */ \
(Object)->OwnerThread = Thread; \
\
/* Disable APCs if needed */ \
Thread->KernelApcDisable = Thread->KernelApcDisable - \
(Object)->ApcDisable; \
\
/* Check if it's abandoned */ \
if ((Object)->Abandoned) \
{ \
/* Unabandon it */ \
(Object)->Abandoned = FALSE; \
\
/* Return Status */ \
Thread->WaitStatus = STATUS_ABANDONED; \
} \
\
/* Insert it into the Mutant List */ \
InsertHeadList(Thread->MutantListHead.Blink, \
&(Object)->MutantListEntry); \
} \
}
//
// Satisfies the wait of any nonmutant dispatcher object
//
#define KiSatisfyNonMutantWait(Object) \
{ \
if (((Object)->Header.Type & TIMER_OR_EVENT_TYPE) == \
EventSynchronizationObject) \
{ \
/* Synchronization Timers and Events just get un-signaled */ \
(Object)->Header.SignalState = 0; \
} \
else if ((Object)->Header.Type == SemaphoreObject) \
{ \
/* These ones can have multiple states, so we only decrease it */ \
(Object)->Header.SignalState--; \
} \
}
//
// Recalculates the due time
//
PLARGE_INTEGER
FORCEINLINE
KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime,
IN PLARGE_INTEGER DueTime,
IN OUT PLARGE_INTEGER NewDueTime)
{
/* Don't do anything for absolute waits */
if (OriginalDueTime->QuadPart >= 0) return OriginalDueTime;
/* Otherwise, query the interrupt time and recalculate */
NewDueTime->QuadPart = KeQueryInterruptTime();
NewDueTime->QuadPart -= DueTime->QuadPart;
return NewDueTime;
}
//
// Determines whether a thread should be added to the wait list
//
FORCEINLINE
BOOLEAN
KiCheckThreadStackSwap(IN PKTHREAD Thread,
IN KPROCESSOR_MODE WaitMode)
{
/* Check the required conditions */
if ((WaitMode != KernelMode) &&
(Thread->EnableStackSwap) &&
(Thread->Priority >= (LOW_REALTIME_PRIORITY + 9)))
{
/* We are go for swap */
return TRUE;
}
else
{
/* Don't swap the thread */
return FALSE;
}
}
//
// Adds a thread to the wait list
//
#define KiAddThreadToWaitList(Thread, Swappable) \
{ \
/* Make sure it's swappable */ \
if (Swappable) \
{ \
/* Insert it into the PRCB's List */ \
InsertTailList(&KeGetCurrentPrcb()->WaitListHead, \
&Thread->WaitListEntry); \
} \
}
//
// Checks if a wait in progress should be interrupted by APCs or an alertable
// state.
//
FORCEINLINE
NTSTATUS
KiCheckAlertability(IN PKTHREAD Thread,
IN BOOLEAN Alertable,
IN KPROCESSOR_MODE WaitMode)
{
/* Check if the wait is alertable */
if (Alertable)
{
/* It is, first check if the thread is alerted in this mode */
if (Thread->Alerted[WaitMode])
{
/* It is, so bail out of the wait */
Thread->Alerted[WaitMode] = FALSE;
return STATUS_ALERTED;
}
else if ((WaitMode != KernelMode) &&
(!IsListEmpty(&Thread->ApcState.ApcListHead[UserMode])))
{
/* It's isn't, but this is a user wait with queued user APCs */
Thread->ApcState.UserApcPending = TRUE;
return STATUS_USER_APC;
}
else if (Thread->Alerted[KernelMode])
{
/* It isn't that either, but we're alered in kernel mode */
Thread->Alerted[KernelMode] = FALSE;
return STATUS_ALERTED;
}
}
else if ((WaitMode != KernelMode) && (Thread->ApcState.UserApcPending))
{
/* Not alertable, but this is a user wait with pending user APCs */
return STATUS_USER_APC;
}
/* Otherwise, we're fine */
return STATUS_WAIT_0;
}
//
// Called by Wait and Queue code to insert a timer for dispatching.
// Also called by KeSetTimerEx to insert a timer from the caller.
//
VOID
FORCEINLINE
KxInsertTimer(IN PKTIMER Timer,
IN ULONG Hand)
{
PKSPIN_LOCK_QUEUE LockQueue;
/* Acquire the lock and release the dispatcher lock */
LockQueue = KiAcquireTimerLock(Hand);
KiReleaseDispatcherLockFromDpcLevel();
/* Try to insert the timer */
if (KiInsertTimerTable(Timer, Hand))
{
/* Complete it */
KiCompleteTimer(Timer, LockQueue);
}
else
{
/* Do nothing, just release the lock */
KiReleaseTimerLock(LockQueue);
}
}
//
// Called from Unlink and Queue Insert Code.
// Also called by timer code when canceling an inserted timer.
// Removes a timer from it's tree.
//
VOID
FORCEINLINE
KxRemoveTreeTimer(IN PKTIMER Timer)
{
ULONG Hand = Timer->Header.Hand;
PKSPIN_LOCK_QUEUE LockQueue;
PKTIMER_TABLE_ENTRY TimerEntry;
/* Acquire timer lock */
LockQueue = KiAcquireTimerLock(Hand);
/* Set the timer as non-inserted */
Timer->Header.Inserted = FALSE;
/* Remove it from the timer list */
if (RemoveEntryList(&Timer->TimerListEntry))
{
/* Get the entry and check if it's empty */
TimerEntry = &KiTimerTableListHead[Hand];
if (IsListEmpty(&TimerEntry->Entry))
{
/* Clear the time then */
TimerEntry->Time.HighPart = 0xFFFFFFFF;
}
}
/* Release the timer lock */
KiReleaseTimerLock(LockQueue);
}
VOID
FORCEINLINE
KxSetTimerForThreadWait(IN PKTIMER Timer,
IN LARGE_INTEGER Interval,
OUT PULONG Hand)
{
ULONGLONG DueTime;
LARGE_INTEGER InterruptTime, SystemTime, TimeDifference;
/* Check the timer's interval to see if it's absolute */
Timer->Header.Absolute = FALSE;
if (Interval.HighPart >= 0)
{
/* Get the system time and calculate the relative time */
KeQuerySystemTime(&SystemTime);
TimeDifference.QuadPart = SystemTime.QuadPart - Interval.QuadPart;
Timer->Header.Absolute = TRUE;
/* Check if we've already expired */
if (TimeDifference.HighPart >= 0)
{
/* Reset everything */
Timer->DueTime.QuadPart = 0;
*Hand = 0;
Timer->Header.Hand = 0;
return;
}
else
{
/* Update the interval */
Interval = TimeDifference;
}
}
/* Calculate the due time */
InterruptTime.QuadPart = KeQueryInterruptTime();
DueTime = InterruptTime.QuadPart - Interval.QuadPart;
Timer->DueTime.QuadPart = DueTime;
/* Calculate the timer handle */
*Hand = KiComputeTimerTableIndex(DueTime);
Timer->Header.Hand = (UCHAR)*Hand;
}
#define KxDelayThreadWait() \
\
/* Setup the Wait Block */ \
Thread->WaitBlockList = TimerBlock; \
\
/* Setup the timer */ \
KxSetTimerForThreadWait(Timer, *Interval, &Hand); \
\
/* Save the due time for the caller */ \
DueTime.QuadPart = Timer->DueTime.QuadPart; \
\
/* Link the timer to this Wait Block */ \
TimerBlock->NextWaitBlock = TimerBlock; \
Timer->Header.WaitListHead.Flink = &TimerBlock->WaitListEntry; \
Timer->Header.WaitListHead.Blink = &TimerBlock->WaitListEntry; \
\
/* Clear wait status */ \
Thread->WaitStatus = STATUS_SUCCESS; \
\
/* Setup wait fields */ \
Thread->Alertable = Alertable; \
Thread->WaitReason = DelayExecution; \
Thread->WaitMode = WaitMode; \
\
/* 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 KxMultiThreadWait() \
/* Link wait block array to the thread */ \
Thread->WaitBlockList = WaitBlockArray; \
\
/* Reset the index */ \
Index = 0; \
\
/* Loop wait blocks */ \
do \
{ \
/* Fill out the wait block */ \
WaitBlock = &WaitBlockArray[Index]; \
WaitBlock->Object = Object[Index]; \
WaitBlock->WaitKey = (USHORT)Index; \
WaitBlock->WaitType = WaitType; \
WaitBlock->Thread = Thread; \
\
/* Link to next block */ \
WaitBlock->NextWaitBlock = &WaitBlockArray[Index + 1]; \
Index++; \
} while (Index < Count); \
\
/* Link the last block */ \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -