- Add KiCheckThreadStackSwap and KiAddThreadToWaitList macros

- Initialize PRCBs' Wait Lists
- Fix a ghastly implementation fault where the the queue code was correctly removing the thread from its wait list, but where this wait list was actually connected to the _SCHEDULER_ and ended up removing a thread behind its back, causing bizarre issues and w3seek's ASSERT(State == Ready) bug. Fixed this by using the macros above and PRCB Wait List and properly inserting a waiting thread into that list, and then removing it when unblocking it or removing a queue.

svn path=/trunk/; revision=23056
This commit is contained in:
Alex Ionescu 2006-07-14 01:03:27 +00:00
parent 8d372c2271
commit 1f1857f96d
5 changed files with 64 additions and 4 deletions

View file

@ -155,6 +155,40 @@
} \
}
//
// 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; \
} \
}
//
// 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); \
} \
}
//
// Rules for checking alertability:
// - For Alertable waits ONLY:

View file

@ -252,6 +252,7 @@ KeApplicationProcessorInit(VOID)
KiCheckFPU();
KeInitDpc(Pcr->Prcb);
InitializeListHead(&Pcr->PrcbData.WaitListHead);
if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL)
{
@ -332,6 +333,7 @@ KeInit1(PCHAR CommandLine, PULONG LastKernelAddress)
KPCR->NtTib.ExceptionList = (PVOID)-1;
KeInitDpc(KPCR->Prcb);
InitializeListHead(&KPCR->PrcbData.WaitListHead);
KeInitExceptions ();
KeInitInterrupts ();

View file

@ -83,7 +83,7 @@ KiScanThreadList(KPRIORITY Priority,
if (current->State != Ready) {
DPRINT1("%d/%d\n", &current, current->State);
DPRINT1("%p/%d\n", current, current->State);
}
ASSERT(current->State == Ready);

View file

@ -102,7 +102,7 @@ KiInsertQueue(IN PKQUEUE Queue,
/* Remove the queue from the thread's wait list */
Thread->WaitStatus = (NTSTATUS)Entry;
RemoveEntryList(&Thread->WaitListEntry);
if (Thread->WaitListEntry.Flink) RemoveEntryList(&Thread->WaitListEntry);
Thread->WaitReason = 0;
/* Increase the active threads and set the status*/
@ -248,6 +248,7 @@ KeRemoveQueue(IN PKQUEUE Queue,
PKQUEUE PreviousQueue;
PKWAIT_BLOCK WaitBlock;
PKTIMER Timer;
BOOLEAN Swappable;
ASSERT_QUEUE(Queue);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
@ -354,6 +355,10 @@ KeRemoveQueue(IN PKQUEUE Queue,
WaitBlock->Thread = Thread;
Thread->WaitStatus = STATUS_WAIT_0;
/* Check if we can swap the thread's stack */
Thread->WaitListEntry.Flink = NULL;
KiCheckThreadStackSwap(WaitMode, Thread, Swappable);
/* We need to wait for the object... check for a timeout */
if (Timeout)
{
@ -406,6 +411,7 @@ KeRemoveQueue(IN PKQUEUE Queue,
Thread->State = Waiting;
/* Find a new thread to run */
KiAddThreadToWaitList(Thread, Swappable);
Status = KiSwapThread();
/* Reset the wait reason */

View file

@ -143,8 +143,8 @@ KiAbortWaitThread(IN PKTHREAD Thread,
WaitBlock = WaitBlock->NextWaitBlock;
} while (WaitBlock != Thread->WaitBlockList);
/* FIXME: Remove the thread from the wait list! */
//RemoveEntryList(&Thread->WaitListEntry);
/* Remove the thread from the wait list! */
if (Thread->WaitListEntry.Flink) RemoveEntryList(&Thread->WaitListEntry);
/* Check if there's a Thread Timer */
Timer = &Thread->Timer;
@ -274,6 +274,7 @@ KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode,
PKTIMER ThreadTimer;
PKTHREAD CurrentThread = KeGetCurrentThread();
NTSTATUS WaitStatus = STATUS_SUCCESS;
BOOLEAN Swappable;
/* Check if the lock is already held */
if (CurrentThread->WaitNext)
@ -306,6 +307,10 @@ KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode,
/* Check if we can do an alertable wait, if requested */
KiCheckAlertability();
/* Check if we can swap the thread's stack */
CurrentThread->WaitListEntry.Flink = NULL;
KiCheckThreadStackSwap(WaitMode, CurrentThread, Swappable);
/* Set status */
CurrentThread->WaitStatus = STATUS_WAIT_0;
@ -341,6 +346,7 @@ KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode,
CurrentThread->State = Waiting;
/* Find a new thread to run */
KiAddThreadToWaitList(CurrentThread, Swappable);
WaitStatus = KiSwapThread();
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
@ -383,6 +389,7 @@ KeWaitForSingleObject(PVOID Object,
PKTIMER ThreadTimer;
PKTHREAD CurrentThread = KeGetCurrentThread();
NTSTATUS WaitStatus = STATUS_SUCCESS;
BOOLEAN Swappable;
/* Check if the lock is already held */
if (CurrentThread->WaitNext)
@ -461,6 +468,10 @@ KeWaitForSingleObject(PVOID Object,
/* 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)
{
@ -512,6 +523,7 @@ KeWaitForSingleObject(PVOID Object,
CurrentThread->State = Waiting;
/* Find a new thread to run */
KiAddThreadToWaitList(CurrentThread, Swappable);
WaitStatus = KiSwapThread();
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
@ -564,6 +576,7 @@ KeWaitForMultipleObjects(IN ULONG Count,
ULONG AllObjectsSignaled;
ULONG WaitIndex;
NTSTATUS WaitStatus = STATUS_SUCCESS;
BOOLEAN Swappable;
/* Set the Current Thread */
CurrentThread = KeGetCurrentThread();
@ -727,6 +740,10 @@ KeWaitForMultipleObjects(IN ULONG Count,
/* 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)
{
@ -786,6 +803,7 @@ KeWaitForMultipleObjects(IN ULONG Count,
CurrentThread->State = Waiting;
/* Find a new thread to run */
KiAddThreadToWaitList(CurrentThread, Swappable);
WaitStatus = KiSwapThread();
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);