- Converted some macros to inlined functions.

- Modified KeDelayExecutionThread and KeWaitForSingleObject to be much simpler and readable, reducing some of the loops and continues, and 4th-level indentation. Also packed up common wait initialization at the beginning of the function, and into two new inline functions: KxDelayThreadWait and KxSingleThreadWait. No actual semantic changes, just re-ordering.
- Rename KiUnwakeQueue to KiActivateWaiterQueue.

svn path=/trunk/; revision=24110
This commit is contained in:
Alex Ionescu 2006-09-14 15:48:02 +00:00
parent bb617c9ac9
commit 1b75e6549e
6 changed files with 338 additions and 291 deletions

View file

@ -622,7 +622,7 @@ KeRemoveQueueApc(PKAPC Apc);
VOID
FASTCALL
KiWakeQueue(IN PKQUEUE Queue);
KiActivateWaiterQueue(IN PKQUEUE Queue);
/* INITIALIZATION FUNCTIONS *************************************************/

View file

@ -219,21 +219,24 @@ KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime,
//
// Determines wether a thread should be added to the wait list
//
#define KiCheckThreadStackSwap(WaitMode, Thread, Swappable) \
{ \
/* Check the required conditions */ \
if ((WaitMode != KernelMode) && \
(Thread->EnableStackSwap) && \
(Thread->Priority >= (LOW_REALTIME_PRIORITY + 9))) \
{ \
/* We are go for swap */ \
Swappable = TRUE; \
} \
else \
{ \
/* Don't swap the thread */ \
Swappable = FALSE; \
} \
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;
}
}
//
@ -251,45 +254,134 @@ KiRecalculateDueTime(IN PLARGE_INTEGER OriginalDueTime,
}
//
// Rules for checking alertability:
// - For Alertable waits ONLY:
// * We don't wait and return STATUS_ALERTED if the thread is alerted
// in EITHER the specified wait mode OR in Kernel Mode.
// - For BOTH Alertable AND Non-Alertable waits:
// * We don't want and return STATUS_USER_APC if the User Mode APC list
// is not empty AND the wait mode is User Mode.
// Checks if a wait in progress should be interrupted by APCs or an alertable
// state.
//
#define KiCheckAlertability() \
{ \
if (Alertable) \
{ \
if (CurrentThread->Alerted[(int)WaitMode]) \
{ \
CurrentThread->Alerted[(int)WaitMode] = FALSE; \
WaitStatus = STATUS_ALERTED; \
break; \
} \
else if ((WaitMode != KernelMode) && \
(!IsListEmpty(&CurrentThread-> \
ApcState.ApcListHead[UserMode]))) \
{ \
CurrentThread->ApcState.UserApcPending = TRUE; \
WaitStatus = STATUS_USER_APC; \
break; \
} \
else if (CurrentThread->Alerted[KernelMode]) \
{ \
CurrentThread->Alerted[KernelMode] = FALSE; \
WaitStatus = STATUS_ALERTED; \
break; \
} \
} \
else if ((WaitMode != KernelMode) && \
(CurrentThread->ApcState.UserApcPending)) \
{ \
WaitStatus = STATUS_USER_APC; \
break; \
} \
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;
}
FORCEINLINE
BOOLEAN
KxDelayThreadWait(IN PKTHREAD Thread,
IN BOOLEAN Alertable,
IN KPROCESSOR_MODE WaitMode)
{
BOOLEAN Swappable;
PKWAIT_BLOCK TimerBlock = &Thread->WaitBlock[TIMER_WAIT_BLOCK];
/* Setup the Wait Block */
Thread->WaitBlockList = TimerBlock;
TimerBlock->NextWaitBlock = TimerBlock;
/* Link the timer to this Wait Block */
Thread->Timer.Header.WaitListHead.Flink = &TimerBlock->WaitListEntry;
Thread->Timer.Header.WaitListHead.Blink = &TimerBlock->WaitListEntry;
/* Clear wait status */
Thread->WaitStatus = STATUS_WAIT_0;
/* 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 = ((PLARGE_INTEGER)&KeTickCount)->LowPart;
return Swappable;
}
FORCEINLINE
BOOLEAN
KxSingleThreadWait(IN PKTHREAD Thread,
IN PKWAIT_BLOCK WaitBlock,
IN PVOID Object,
IN PLARGE_INTEGER Timeout,
IN BOOLEAN Alertable,
IN KWAIT_REASON WaitReason,
IN KPROCESSOR_MODE WaitMode)
{
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;
}
//

View file

@ -111,7 +111,7 @@ KeWaitForGate(IN PKGATE Gate,
if (Queue)
{
/* Wake it up */
KiWakeQueue(Queue);
KiActivateWaiterQueue(Queue);
/* Release the dispatcher lock */
KiReleaseDispatcherLockFromDpcLevel();

View file

@ -21,7 +21,7 @@
*/
VOID
FASTCALL
KiWakeQueue(IN PKQUEUE Queue)
KiActivateWaiterQueue(IN PKQUEUE Queue)
{
PLIST_ENTRY QueueEntry;
PLIST_ENTRY WaitEntry;
@ -285,7 +285,7 @@ KeRemoveQueue(IN PKQUEUE Queue,
RemoveEntryList(QueueEntry);
/* Wake the queue */
KiWakeQueue(PreviousQueue);
KiActivateWaiterQueue(PreviousQueue);
}
/* Insert in this new Queue */
@ -359,7 +359,7 @@ KeRemoveQueue(IN PKQUEUE Queue,
/* Check if we can swap the thread's stack */
Thread->WaitListEntry.Flink = NULL;
KiCheckThreadStackSwap(WaitMode, Thread, Swappable);
Swappable = KiCheckThreadStackSwap(Thread, WaitMode);
/* We need to wait for the object... check for a timeout */
if (Timeout)

View file

@ -1324,7 +1324,7 @@ KeTerminateThread(IN KPRIORITY Increment)
{
/* Remove it from the list, and handle the queue */
RemoveEntryList(&Thread->QueueListEntry);
KiWakeQueue(Thread->Queue);
KiActivateWaiterQueue(Thread->Queue);
}
/* Signal the thread */

View file

@ -280,113 +280,88 @@ KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode,
IN BOOLEAN Alertable,
IN PLARGE_INTEGER Interval OPTIONAL)
{
PKWAIT_BLOCK TimerWaitBlock;
PKTIMER ThreadTimer;
PKTHREAD CurrentThread = KeGetCurrentThread();
NTSTATUS WaitStatus = STATUS_SUCCESS;
PKTHREAD Thread = KeGetCurrentThread();
NTSTATUS WaitStatus;
BOOLEAN Swappable;
PLARGE_INTEGER OriginalDueTime = Interval;
LARGE_INTEGER DueTime, NewDueTime;
/* Check if the lock is already held */
if (CurrentThread->WaitNext)
if (Thread->WaitNext)
{
/* Lock is held, disable Wait Next */
CurrentThread->WaitNext = FALSE;
Thread->WaitNext = FALSE;
Swappable = KxDelayThreadWait(Thread, Alertable, WaitMode);
}
else
{
/* Lock not held, acquire it */
CurrentThread->WaitIrql = KiAcquireDispatcherLock();
WaitStart:
Thread->WaitIrql = KiAcquireDispatcherLock();
Swappable = KxDelayThreadWait(Thread, Alertable, WaitMode);
}
/* Use built-in Wait block */
TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
/* Start Wait Loop */
do
/* Check if a kernel APC is pending and we're below APC_LEVEL */
if ((Thread->ApcState.KernelApcPending) && !(Thread->SpecialApcDisable) &&
(Thread->WaitIrql < APC_LEVEL))
{
/* Check if a kernel APC is pending and we're below APC_LEVEL */
if ((CurrentThread->ApcState.KernelApcPending) &&
!(CurrentThread->SpecialApcDisable) &&
(CurrentThread->WaitIrql < APC_LEVEL))
{
/* Unlock the dispatcher */
KiReleaseDispatcherLock(CurrentThread->WaitIrql);
}
else
{
/* Check if we can do an alertable wait, if requested */
KiCheckAlertability();
/* Unlock the dispatcher */
KiReleaseDispatcherLock(Thread->WaitIrql);
goto WaitStart;
}
/* Check if we can swap the thread's stack */
CurrentThread->WaitListEntry.Flink = NULL;
KiCheckThreadStackSwap(WaitMode, CurrentThread, Swappable);
/* Check if we have to bail out due to an alerted state */
WaitStatus = KiCheckAlertability(Thread, Alertable, WaitMode);
if (WaitStatus != STATUS_WAIT_0)
{
/* Unlock the dispatcher and return */
KiReleaseDispatcherLock(Thread->WaitIrql);
return WaitStatus;
}
/* Set status */
CurrentThread->WaitStatus = STATUS_WAIT_0;
/* Set Timer */
ThreadTimer = &Thread->Timer;
/* Set Timer */
ThreadTimer = &CurrentThread->Timer;
/* Insert the Timer into the Timer Lists and enable it */
if (!KiInsertTimer(ThreadTimer, *Interval))
{
/* FIXME: We should find a new ready thread */
KiReleaseDispatcherLock(Thread->WaitIrql);
return STATUS_WAIT_0;
}
/* Setup the Wait Block */
CurrentThread->WaitBlockList = TimerWaitBlock;
TimerWaitBlock->NextWaitBlock = TimerWaitBlock;
/* Save due time */
DueTime.QuadPart = ThreadTimer->DueTime.QuadPart;
/* Link the timer to this Wait Block */
ThreadTimer->Header.WaitListHead.Flink =
&TimerWaitBlock->WaitListEntry;
ThreadTimer->Header.WaitListHead.Blink =
&TimerWaitBlock->WaitListEntry;
/* Handle Kernel Queues */
if (Thread->Queue) KiActivateWaiterQueue(Thread->Queue);
/* Insert the Timer into the Timer Lists and enable it */
if (!KiInsertTimer(ThreadTimer, *Interval))
{
/* FIXME: We should find a new ready thread */
WaitStatus = STATUS_SUCCESS;
break;
}
/* Setup the wait information */
Thread->State = Waiting;
/* Save due time */
DueTime.QuadPart = ThreadTimer->DueTime.QuadPart;
/* Add the thread to the wait list */
KiAddThreadToWaitList(Thread, Swappable);
/* Handle Kernel Queues */
if (CurrentThread->Queue) KiWakeQueue(CurrentThread->Queue);
/* Swap the thread */
ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL);
KiSetThreadSwapBusy(Thread);
WaitStatus = KiSwapThread(Thread, KeGetCurrentPrcb());
/* Setup the wait information */
CurrentThread->Alertable = Alertable;
CurrentThread->WaitMode = WaitMode;
CurrentThread->WaitReason = DelayExecution;
CurrentThread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;
CurrentThread->State = Waiting;
/* Check if we were executing an APC or if we timed out */
if (WaitStatus == STATUS_KERNEL_APC)
{
/* Recalculate due times */
Interval = KiRecalculateDueTime(OriginalDueTime,
&DueTime,
&NewDueTime);
goto WaitStart;
}
/* Find a new thread to run */
KiAddThreadToWaitList(CurrentThread, Swappable);
WaitStatus = KiSwapThread(CurrentThread, KeGetCurrentPrcb());
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* This is a good thing */
if (WaitStatus == STATUS_TIMEOUT) WaitStatus = STATUS_SUCCESS;
/* Check if we were executing an APC or if we timed out */
if (WaitStatus != STATUS_KERNEL_APC)
{
/* This is a good thing */
if (WaitStatus == STATUS_TIMEOUT) WaitStatus = STATUS_SUCCESS;
/* Return Status */
return WaitStatus;
}
/* Recalculate due times */
Interval = KiRecalculateDueTime(OriginalDueTime,
&DueTime,
&NewDueTime);
}
/* Acquire again the lock */
CurrentThread->WaitIrql = KiAcquireDispatcherLock();
} while (TRUE);
/* Release the Lock, we are done */
KiReleaseDispatcherLock(CurrentThread->WaitIrql);
/* Return Status */
return WaitStatus;
}
@ -403,183 +378,163 @@ KeWaitForSingleObject(IN PVOID Object,
{
PKMUTANT CurrentObject;
PKWAIT_BLOCK WaitBlock;
PKWAIT_BLOCK TimerWaitBlock;
PKTIMER ThreadTimer;
PKTHREAD CurrentThread = KeGetCurrentThread();
NTSTATUS WaitStatus = STATUS_SUCCESS;
PKTHREAD Thread = KeGetCurrentThread();
NTSTATUS WaitStatus;
BOOLEAN Swappable;
LARGE_INTEGER DueTime, NewDueTime;
PLARGE_INTEGER OriginalDueTime = Timeout;
/* Get wait block */
WaitBlock = &Thread->WaitBlock[0];
/* Check if the lock is already held */
if (CurrentThread->WaitNext)
if (Thread->WaitNext)
{
/* Lock is held, disable Wait Next */
CurrentThread->WaitNext = FALSE;
Thread->WaitNext = FALSE;
Swappable = KxSingleThreadWait(Thread,
WaitBlock,
Object,
Timeout,
Alertable,
WaitReason,
WaitMode);
}
else
{
StartWait:
/* Lock not held, acquire it */
CurrentThread->WaitIrql = KiAcquireDispatcherLock();
Thread->WaitIrql = KiAcquireDispatcherLock();
Swappable = KxSingleThreadWait(Thread,
WaitBlock,
Object,
Timeout,
WaitReason,
WaitMode,
Alertable);
}
/* Start the actual Loop */
WaitBlock = &CurrentThread->WaitBlock[0];
do
/* Check if a kernel APC is pending and we're below APC_LEVEL */
if ((Thread->ApcState.KernelApcPending) && !(Thread->SpecialApcDisable) &&
(Thread->WaitIrql < APC_LEVEL))
{
/* Check if a kernel APC is pending and we're below APC_LEVEL */
if ((CurrentThread->ApcState.KernelApcPending) &&
!(CurrentThread->SpecialApcDisable) &&
(CurrentThread->WaitIrql < APC_LEVEL))
{
/* Unlock the dispatcher */
KiReleaseDispatcherLock(CurrentThread->WaitIrql);
}
else
{
/* Set default status */
CurrentThread->WaitStatus = STATUS_WAIT_0;
/* Unlock the dispatcher and wait again */
KiReleaseDispatcherLock(Thread->WaitIrql);
goto StartWait;
}
/* Get the Current Object */
CurrentObject = (PKMUTANT)Object;
/* Get the Current Object */
CurrentObject = (PKMUTANT)Object;
ASSERT(CurrentObject->Header.Type != QueueObject);
/* Check if it's a mutant */
if (CurrentObject->Header.Type == MutantObject)
/* Check if it's a mutant */
if (CurrentObject->Header.Type == MutantObject)
{
/* Check its signal state or if we own it */
if ((CurrentObject->Header.SignalState > 0) ||
(Thread == CurrentObject->OwnerThread))
{
/* Just unwait this guy and exit */
if (CurrentObject->Header.SignalState != (LONG)MINLONG)
{
/* Check its signal state or if we own it */
if ((CurrentObject->Header.SignalState > 0) ||
(CurrentThread == CurrentObject->OwnerThread))
{
/* Just unwait this guy and exit */
if (CurrentObject->Header.SignalState != (LONG)MINLONG)
{
/* It has a normal signal state. Unwait and return */
KiSatisfyMutantWait(CurrentObject, CurrentThread);
WaitStatus = CurrentThread->WaitStatus;
goto DontWait;
}
else
{
/* Raise an exception (see wasm.ru) */
KiReleaseDispatcherLock(CurrentThread->
WaitIrql);
ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
}
}
}
else if (CurrentObject->Header.SignalState > 0)
{
/* Another satisfied object */
KiSatisfyNonMutantWait(CurrentObject, CurrentThread);
WaitStatus = STATUS_WAIT_0;
/* It has a normal signal state. Unwait and return */
KiSatisfyMutantWait(CurrentObject, Thread);
WaitStatus = Thread->WaitStatus;
goto DontWait;
}
/* Append wait block to the KTHREAD wait block list */
CurrentThread->WaitBlockList = WaitBlock;
/* Set up the Wait Block */
WaitBlock->Object = CurrentObject;
WaitBlock->WaitKey = (USHORT)(STATUS_SUCCESS);
WaitBlock->WaitType = WaitAny;
/* Make sure we can satisfy the Alertable request */
KiCheckAlertability();
/* Check if we can swap the thread's stack */
CurrentThread->WaitListEntry.Flink = NULL;
KiCheckThreadStackSwap(WaitMode, CurrentThread, Swappable);
/* Enable the Timeout Timer if there was any specified */
if (Timeout)
{
/* Fail if the timeout interval is actually 0 */
if (!Timeout->QuadPart)
{
/* Return a timeout */
WaitStatus = STATUS_TIMEOUT;
goto DontWait;
}
/* Point to Timer Wait Block and Thread Timer */
TimerWaitBlock = &CurrentThread->WaitBlock[TIMER_WAIT_BLOCK];
ThreadTimer = &CurrentThread->Timer;
/* Connect the Timer Wait Block */
WaitBlock->NextWaitBlock = TimerWaitBlock;
/* Set up the Timer Wait Block */
TimerWaitBlock->NextWaitBlock = WaitBlock;
/* Link the timer to this Wait Block */
ThreadTimer->Header.WaitListHead.Flink =
&TimerWaitBlock->WaitListEntry;
ThreadTimer->Header.WaitListHead.Blink =
&TimerWaitBlock->WaitListEntry;
/* Insert the Timer into the Timer Lists and enable it */
if (!KiInsertTimer(ThreadTimer, *Timeout))
{
/* Return a timeout if we couldn't insert the timer */
WaitStatus = STATUS_TIMEOUT;
goto DontWait;
}
/* Set the current due time */
DueTime.QuadPart = ThreadTimer->DueTime.QuadPart;
}
else
{
/* No timer block, so just set our wait block as next */
WaitBlock->NextWaitBlock = WaitBlock;
}
/* Raise an exception */
KiReleaseDispatcherLock(Thread->WaitIrql);
ExRaiseStatus(STATUS_MUTANT_LIMIT_EXCEEDED);
}
}
}
else if (CurrentObject->Header.SignalState > 0)
{
/* Another satisfied object */
KiSatisfyNonMutantWait(CurrentObject, Thread);
WaitStatus = STATUS_WAIT_0;
goto DontWait;
}
/* Link the Object to this Wait Block */
InsertTailList(&CurrentObject->Header.WaitListHead,
&WaitBlock->WaitListEntry);
/* Make sure we can satisfy the Alertable request */
WaitStatus = KiCheckAlertability(Thread, Alertable, WaitMode);
if (WaitStatus != STATUS_WAIT_0)
{
/* Unlock the dispatcher and return */
KiReleaseDispatcherLock(Thread->WaitIrql);
return WaitStatus;
}
/* Handle Kernel Queues */
if (CurrentThread->Queue) KiWakeQueue(CurrentThread->Queue);
/* Setup the wait information */
CurrentThread->Alertable = Alertable;
CurrentThread->WaitMode = WaitMode;
CurrentThread->WaitReason = WaitReason;
CurrentThread->WaitTime = ((PLARGE_INTEGER)&KeTickCount)->LowPart;
CurrentThread->State = Waiting;
/* Find a new thread to run */
KiAddThreadToWaitList(CurrentThread, Swappable);
WaitStatus = KiSwapThread(CurrentThread, KeGetCurrentPrcb());
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Check if we were executing an APC */
if (WaitStatus != STATUS_KERNEL_APC) return WaitStatus;
/* Check if we had a timeout */
if (Timeout)
{
/* Recalculate due times */
Timeout = KiRecalculateDueTime(OriginalDueTime,
&DueTime,
&NewDueTime);
}
/* Enable the Timeout Timer if there was any specified */
if (Timeout)
{
/* Fail if the timeout interval is actually 0 */
if (!Timeout->QuadPart)
{
/* Return a timeout */
WaitStatus = STATUS_TIMEOUT;
goto DontWait;
}
/* Acquire again the lock */
CurrentThread->WaitIrql = KiAcquireDispatcherLock();
} while (TRUE);
/* Insert the Timer into the Timer Lists and enable it */
ThreadTimer = &Thread->Timer;
if (!KiInsertTimer(ThreadTimer, *Timeout))
{
/* Return a timeout if we couldn't insert the timer */
WaitStatus = STATUS_TIMEOUT;
goto DontWait;
}
/* Release the Lock, we are done */
KiReleaseDispatcherLock(CurrentThread->WaitIrql);
/* Set the current due time */
DueTime.QuadPart = ThreadTimer->DueTime.QuadPart;
}
/* Link the Object to this Wait Block */
InsertTailList(&CurrentObject->Header.WaitListHead,
&WaitBlock->WaitListEntry);
/* Handle Kernel Queues */
if (Thread->Queue) KiActivateWaiterQueue(Thread->Queue);
/* Setup the wait information */
Thread->State = Waiting;
/* Add the thread to the wait list */
KiAddThreadToWaitList(Thread, Swappable);
/* Swap the thread */
ASSERT(Thread->WaitIrql <= DISPATCH_LEVEL);
KiSetThreadSwapBusy(Thread);
WaitStatus = KiSwapThread(Thread, KeGetCurrentPrcb());
/* Check if we were executing an APC */
if (WaitStatus == STATUS_KERNEL_APC)
{
/* Check if we had a timeout */
if (Timeout)
{
/* Recalculate due times */
Timeout = KiRecalculateDueTime(OriginalDueTime,
&DueTime,
&NewDueTime);
}
/* Wait again */
goto StartWait;
}
/* Wait complete */
return WaitStatus;
DontWait:
/* Adjust the Quantum */
KiAdjustQuantumThread(CurrentThread);
KiAdjustQuantumThread(Thread);
/* Release & Return */
KiReleaseDispatcherLock(CurrentThread->WaitIrql);
KiReleaseDispatcherLock(Thread->WaitIrql);
return WaitStatus;
}
@ -769,11 +724,11 @@ KeWaitForMultipleObjects(IN ULONG Count,
}
/* Make sure we can satisfy the Alertable request */
KiCheckAlertability();
WaitStatus = KiCheckAlertability(CurrentThread, Alertable, WaitMode);
/* Check if we can swap the thread's stack */
CurrentThread->WaitListEntry.Flink = NULL;
KiCheckThreadStackSwap(WaitMode, CurrentThread, Swappable);
Swappable = KiCheckThreadStackSwap(CurrentThread, WaitMode);
/* Enable the Timeout Timer if there was any specified */
if (Timeout)
@ -827,7 +782,7 @@ KeWaitForMultipleObjects(IN ULONG Count,
} while (WaitBlock != WaitBlockArray);
/* Handle Kernel Queues */
if (CurrentThread->Queue) KiWakeQueue(CurrentThread->Queue);
if (CurrentThread->Queue) KiActivateWaiterQueue(CurrentThread->Queue);
/* Setup the wait information */
CurrentThread->Alertable = Alertable;
@ -880,22 +835,22 @@ NtDelayExecution(IN BOOLEAN Alertable,
LARGE_INTEGER SafeInterval;
NTSTATUS Status = STATUS_SUCCESS;
/* Check if parameters are valid */
/* Check the previous mode */
if(PreviousMode != KernelMode)
{
/* Enter SEH for probing */
_SEH_TRY
{
/* make a copy on the kernel stack and let DelayInterval point to it so
we don't need to wrap KeDelayExecutionThread in SEH! */
/* Probe and capture the time out */
SafeInterval = ProbeForReadLargeInteger(DelayInterval);
DelayInterval = &SafeInterval;
}
_SEH_HANDLE
{
/* Get SEH exception */
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if (!NT_SUCCESS(Status)) return Status;
}