Author: ion Date: Fri Jul 14 05:03:27 2006 New Revision: 23056
URL: http://svn.reactos.org/svn/reactos?rev=23056&view=rev Log: - 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.
Modified: trunk/reactos/ntoskrnl/include/internal/ke_x.h trunk/reactos/ntoskrnl/ke/i386/kernel.c trunk/reactos/ntoskrnl/ke/kthread.c trunk/reactos/ntoskrnl/ke/queue.c trunk/reactos/ntoskrnl/ke/wait.c
Modified: trunk/reactos/ntoskrnl/include/internal/ke_x.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke_x.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ke_x.h Fri Jul 14 05:03:27 2006 @@ -156,6 +156,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: // * We don't wait and return STATUS_ALERTED if the thread is alerted
Modified: trunk/reactos/ntoskrnl/ke/i386/kernel.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kernel.c?r... ============================================================================== --- trunk/reactos/ntoskrnl/ke/i386/kernel.c (original) +++ trunk/reactos/ntoskrnl/ke/i386/kernel.c Fri Jul 14 05:03:27 2006 @@ -252,6 +252,7 @@ KiCheckFPU();
KeInitDpc(Pcr->Prcb); + InitializeListHead(&Pcr->PrcbData.WaitListHead);
if (Pcr->PrcbData.FeatureBits & X86_FEATURE_SYSCALL) { @@ -332,6 +333,7 @@ KPCR->NtTib.ExceptionList = (PVOID)-1;
KeInitDpc(KPCR->Prcb); + InitializeListHead(&KPCR->PrcbData.WaitListHead);
KeInitExceptions (); KeInitInterrupts ();
Modified: trunk/reactos/ntoskrnl/ke/kthread.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/kthread.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ke/kthread.c (original) +++ trunk/reactos/ntoskrnl/ke/kthread.c Fri Jul 14 05:03:27 2006 @@ -83,7 +83,7 @@
if (current->State != Ready) {
- DPRINT1("%d/%d\n", ¤t, current->State); + DPRINT1("%p/%d\n", current, current->State); }
ASSERT(current->State == Ready);
Modified: trunk/reactos/ntoskrnl/ke/queue.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/queue.c?rev=230... ============================================================================== --- trunk/reactos/ntoskrnl/ke/queue.c (original) +++ trunk/reactos/ntoskrnl/ke/queue.c Fri Jul 14 05:03:27 2006 @@ -102,7 +102,7 @@
/* 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 @@ PKQUEUE PreviousQueue; PKWAIT_BLOCK WaitBlock; PKTIMER Timer; + BOOLEAN Swappable; ASSERT_QUEUE(Queue); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
@@ -354,6 +355,10 @@ 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 @@ Thread->State = Waiting;
/* Find a new thread to run */ + KiAddThreadToWaitList(Thread, Swappable); Status = KiSwapThread();
/* Reset the wait reason */
Modified: trunk/reactos/ntoskrnl/ke/wait.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/wait.c?rev=2305... ============================================================================== --- trunk/reactos/ntoskrnl/ke/wait.c (original) +++ trunk/reactos/ntoskrnl/ke/wait.c Fri Jul 14 05:03:27 2006 @@ -143,8 +143,8 @@ 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 @@ PKTIMER ThreadTimer; PKTHREAD CurrentThread = KeGetCurrentThread(); NTSTATUS WaitStatus = STATUS_SUCCESS; + BOOLEAN Swappable;
/* Check if the lock is already held */ if (CurrentThread->WaitNext) @@ -305,6 +306,10 @@ { /* 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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ ULONG AllObjectsSignaled; ULONG WaitIndex; NTSTATUS WaitStatus = STATUS_SUCCESS; + BOOLEAN Swappable;
/* Set the Current Thread */ CurrentThread = KeGetCurrentThread(); @@ -727,6 +740,10 @@ /* 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 @@ CurrentThread->State = Waiting;
/* Find a new thread to run */ + KiAddThreadToWaitList(CurrentThread, Swappable); WaitStatus = KiSwapThread(); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);