diff --git a/reactos/ntoskrnl/include/internal/ke_x.h b/reactos/ntoskrnl/include/internal/ke_x.h index 921f023bb48..a56f8725847 100644 --- a/reactos/ntoskrnl/include/internal/ke_x.h +++ b/reactos/ntoskrnl/include/internal/ke_x.h @@ -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: diff --git a/reactos/ntoskrnl/ke/i386/kernel.c b/reactos/ntoskrnl/ke/i386/kernel.c index aec8b839aa7..64a0368ce90 100644 --- a/reactos/ntoskrnl/ke/i386/kernel.c +++ b/reactos/ntoskrnl/ke/i386/kernel.c @@ -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 (); diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index d464d1a5054..ec840ca99ab 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -83,7 +83,7 @@ KiScanThreadList(KPRIORITY Priority, if (current->State != Ready) { - DPRINT1("%d/%d\n", ¤t, current->State); + DPRINT1("%p/%d\n", current, current->State); } ASSERT(current->State == Ready); diff --git a/reactos/ntoskrnl/ke/queue.c b/reactos/ntoskrnl/ke/queue.c index 08223d292d7..91f213d4f22 100644 --- a/reactos/ntoskrnl/ke/queue.c +++ b/reactos/ntoskrnl/ke/queue.c @@ -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 */ diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index e5bdf092a6b..2907728d5f4 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -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);