📄 ke_x.h
字号:
BOOLEAN Swappable;
PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
/* Setup the Wait Block */
Thread->WaitBlockList = WaitBlock;
WaitBlock->WaitKey = STATUS_WAIT_0;
WaitBlock->Object = Object;
WaitBlock->WaitType = WaitAny;
/* Clear wait status */
Thread->WaitStatus = STATUS_WAIT_0;
/* Check if we have a timer */
if (Timeout)
{
/* Pointer to timer block */
WaitBlock->NextWaitBlock = TimerBlock;
TimerBlock->NextWaitBlock = WaitBlock;
/* Link the timer to this Wait Block */
Thread->Timer.Header.WaitListHead.Flink = &TimerBlock->WaitListEntry;
Thread->Timer.Header.WaitListHead.Blink = &TimerBlock->WaitListEntry;
}
else
{
/* No timer block, just ourselves */
WaitBlock->NextWaitBlock = WaitBlock;
}
/* Setup wait fields */
Thread->Alertable = Alertable;
Thread->WaitReason = WaitReason;
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 = ((PLARGE_INTEGER)&KeTickCount)->LowPart;
return Swappable;
}
//
// Unwaits a Thread
//
FORCEINLINE
VOID
KxUnwaitThread(IN DISPATCHER_HEADER *Object,
IN KPRIORITY Increment)
{
PLIST_ENTRY WaitEntry, WaitList;
PKWAIT_BLOCK CurrentWaitBlock;
PKTHREAD WaitThread;
ULONG WaitKey;
/* Loop the Wait Entries */
WaitList = &Object->WaitListHead;
WaitEntry = WaitList->Flink;
do
{
/* Get the current wait block */
CurrentWaitBlock = CONTAINING_RECORD(WaitEntry,
KWAIT_BLOCK,
WaitListEntry);
/* Get the waiting thread */
WaitThread = CurrentWaitBlock->Thread;
/* Check the current Wait Mode */
if (CurrentWaitBlock->WaitType == WaitAny)
{
/* Use the actual wait key */
WaitKey = CurrentWaitBlock->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 CurrentWaitBlock;
PKTHREAD WaitThread;
/* Loop the Wait Entries */
WaitList = &Event->Header.WaitListHead;
WaitEntry = WaitList->Flink;
do
{
/* Get the current wait block */
CurrentWaitBlock = CONTAINING_RECORD(WaitEntry,
KWAIT_BLOCK,
WaitListEntry);
/* Get the waiting thread */
WaitThread = CurrentWaitBlock->Thread;
/* Check the current Wait Mode */
if (CurrentWaitBlock->WaitType == WaitAny)
{
/* Un-signal it */
Event->Header.SignalState = 0;
/* Un-signal the event and unwait the thread */
KiUnwaitThread(WaitThread, CurrentWaitBlock->WaitKey, Increment);
break;
}
else
{
/* Unwait the thread with STATUS_KERNEL_APC */
KiUnwaitThread(WaitThread, STATUS_KERNEL_APC, Increment);
}
/* Next entry */
WaitEntry = WaitList->Flink;
} while (WaitEntry != WaitList);
}
#ifndef _CONFIG_SMP
//
// Spinlock Acquire at IRQL >= DISPATCH_LEVEL
//
FORCEINLINE
VOID
KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
{
/* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
UNREFERENCED_PARAMETER(SpinLock);
}
//
// Spinlock Release at IRQL >= DISPATCH_LEVEL
//
FORCEINLINE
VOID
KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
{
/* On UP builds, spinlocks don't exist at IRQL >= DISPATCH */
UNREFERENCED_PARAMETER(SpinLock);
}
//
// This routine protects against multiple CPU acquires, it's meaningless on UP.
//
VOID
FORCEINLINE
KiAcquireDispatcherObject(IN DISPATCHER_HEADER* Object)
{
UNREFERENCED_PARAMETER(Object);
}
//
// This routine protects against multiple CPU acquires, it's meaningless on UP.
//
VOID
FORCEINLINE
KiReleaseDispatcherObject(IN DISPATCHER_HEADER* Object)
{
UNREFERENCED_PARAMETER(Object);
}
KIRQL
FORCEINLINE
KiAcquireDispatcherLock(VOID)
{
/* Raise to DPC level */
return KeRaiseIrqlToDpcLevel();
}
VOID
FORCEINLINE
KiReleaseDispatcherLock(IN KIRQL OldIrql)
{
/* Just exit the dispatcher */
KiExitDispatcher(OldIrql);
}
VOID
FORCEINLINE
KiAcquireDispatcherLockAtDpcLevel(VOID)
{
/* This is a no-op at DPC Level for UP systems */
return;
}
VOID
FORCEINLINE
KiReleaseDispatcherLockFromDpcLevel(VOID)
{
/* This is a no-op at DPC Level for UP systems */
return;
}
//
// This routine makes the thread deferred ready on the boot CPU.
//
FORCEINLINE
VOID
KiInsertDeferredReadyList(IN PKTHREAD Thread)
{
/* Set the thread to deferred state and boot CPU */
Thread->State = DeferredReady;
Thread->DeferredProcessor = 0;
/* Make the thread ready immediately */
KiDeferredReadyThread(Thread);
}
FORCEINLINE
VOID
KiRescheduleThread(IN BOOLEAN NewThread,
IN ULONG Cpu)
{
/* This is meaningless on UP systems */
UNREFERENCED_PARAMETER(NewThread);
UNREFERENCED_PARAMETER(Cpu);
}
//
// This routine protects against multiple CPU acquires, it's meaningless on UP.
//
FORCEINLINE
VOID
KiSetThreadSwapBusy(IN PKTHREAD Thread)
{
UNREFERENCED_PARAMETER(Thread);
}
//
// This routine protects against multiple CPU acquires, it's meaningless on UP.
//
FORCEINLINE
VOID
KiAcquirePrcbLock(IN PKPRCB Prcb)
{
UNREFERENCED_PARAMETER(Prcb);
}
//
// This routine protects against multiple CPU acquires, it's meaningless on UP.
//
FORCEINLINE
VOID
KiReleasePrcbLock(IN PKPRCB Prcb)
{
UNREFERENCED_PARAMETER(Prcb);
}
//
// This routine protects against multiple CPU acquires, it's meaningless on UP.
//
FORCEINLINE
VOID
KiAcquireThreadLock(IN PKTHREAD Thread)
{
UNREFERENCED_PARAMETER(Thread);
}
//
// This routine protects against multiple CPU acquires, it's meaningless on UP.
//
FORCEINLINE
VOID
KiReleaseThreadLock(IN PKTHREAD Thread)
{
UNREFERENCED_PARAMETER(Thread);
}
//
// This routine protects against multiple CPU acquires, it's meaningless on UP.
//
FORCEINLINE
BOOLEAN
KiTryThreadLock(IN PKTHREAD Thread)
{
UNREFERENCED_PARAMETER(Thread);
return FALSE;
}
FORCEINLINE
VOID
KiCheckDeferredReadyList(IN PKPRCB Prcb)
{
/* There are no deferred ready lists on UP systems */
UNREFERENCED_PARAMETER(Prcb);
}
FORCEINLINE
VOID
KiRundownThread(IN PKTHREAD Thread)
{
/* Check if this is the NPX Thread */
if (KeGetCurrentPrcb()->NpxThread == Thread)
{
/* Clear it */
KeGetCurrentPrcb()->NpxThread = NULL;
Ke386FnInit();
}
}
FORCEINLINE
VOID
KiRequestApcInterrupt(IN BOOLEAN NeedApc,
IN UCHAR Processor)
{
/* We deliver instantly on UP */
UNREFERENCED_PARAMETER(NeedApc);
UNREFERENCED_PARAMETER(Processor);
}
#else
//
// Spinlock Acquisition at IRQL >= DISPATCH_LEVEL
//
FORCEINLINE
VOID
KxAcquireSpinLock(IN PKSPIN_LOCK SpinLock)
{
for (;;)
{
/* Try to acquire it */
if (InterlockedBitTestAndSet((PLONG)SpinLock, 0))
{
/* Value changed... wait until it's locked */
while (*(volatile KSPIN_LOCK *)SpinLock == 1)
{
#ifdef DBG
/* On debug builds, we use a much slower but useful routine */
Kii386SpinOnSpinLock(SpinLock, 5);
#else
/* Otherwise, just yield and keep looping */
YieldProcessor();
#endif
}
}
else
{
#ifdef DBG
/* On debug builds, we OR in the KTHREAD */
*SpinLock = KeGetCurrentThread() | 1;
#endif
/* All is well, break out */
break;
}
}
}
//
// Spinlock Release at IRQL >= DISPATCH_LEVEL
//
FORCEINLINE
VOID
KxReleaseSpinLock(IN PKSPIN_LOCK SpinLock)
{
#ifdef DBG
/* Make sure that the threads match */
if ((KeGetCurrentThread() | 1) != *SpinLock)
{
/* They don't, bugcheck */
KeBugCheckEx(SPIN_LOCK_NOT_OWNED, SpinLock, 0, 0, 0);
}
#endif
/* Clear the lock */
InterlockedAnd(SpinLock, 0);
}
KIRQL
FORCEINLINE
KiAcquireDispatcherObject(IN DISPATCHER_HEADER* Object)
{
LONG OldValue, NewValue;
/* Make sure we're at a safe level to touch the lock */
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
/* Start acquire loop */
do
{
/* Loop until the other CPU releases it */
while ((UCHAR)Object->Lock & KOBJECT_LOCK_BIT)
{
/* Let the CPU know that this is a loop */
YieldProcessor();
};
/* Try acquiring the lock now */
NewValue = InterlockedCompareExchange(&Object->Lock,
OldValue | KOBJECT_LOCK_BIT,
OldValue);
} while (NewValue != OldValue);
}
KIRQL
FORCEINLINE
KiReleaseDispatcherObject(IN DISPATCHER_HEADER* Object)
{
/* Make sure we're at a safe level to touch the lock */
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
/* Release it */
InterlockedAnd(&Object->Lock, ~KOBJECT_LOCK_BIT);
}
KIRQL
FORCEINLINE
KiAcquireDispatcherLock(VOID)
{
/* Raise to synchronization level and acquire the dispatcher lock */
return KeAcquireQueuedSpinLockRaiseToSynch(LockQueueDispatcherLock);
}
VOID
FORCEINLINE
KiReleaseDispatcherLock(IN KIRQL OldIrql)
{
/* First release the lock */
KeReleaseQueuedSpinLockFromDpcLevel(&KeGetCurrentPrcb()->
LockQueue[LockQueueDispatcherLock]);
/* Then exit the dispatcher */
KiExitDispatcher(OldIrql);
}
//
// This routine inserts a thread into the deferred ready list of the given CPU
//
FORCEINLINE
VOID
KiInsertDeferredReadyList(IN PKTHREAD Thread)
{
PKPRCB Prcb = KeGetCurrentPrcb();
/* Set the thread to deferred state and CPU */
Thread->State = DeferredReady;
Thread->DeferredProcessor = Prcb->Number;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -