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/…
==============================================================================
--- 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?…
==============================================================================
--- 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=…
==============================================================================
--- 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=23…
==============================================================================
--- 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=230…
==============================================================================
--- 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);