From 92f9f2e23b4ba040ae4e71523a888f796d37ba37 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Fri, 6 Jan 2006 08:00:09 +0000 Subject: [PATCH] - Invert CONFIG_SMP defines as requested by Hartmut - Remove KiBlockThread and replace by more elegant KiSwapThread which will also make moving to the new scheduler easier. - Handle special case where we have kernel apcs pending and your previous irql was below apc_level during the wait code. - Remove hack to manually unwait a thread during a status of kernel apc. svn path=/trunk/; revision=20605 --- reactos/ntoskrnl/include/internal/ke.h | 27 +++---- reactos/ntoskrnl/ke/gate.c | 15 ++-- reactos/ntoskrnl/ke/kthread.c | 50 +++--------- reactos/ntoskrnl/ke/queue.c | 16 ++-- reactos/ntoskrnl/ke/wait.c | 107 ++++++++++++++++++------- 5 files changed, 123 insertions(+), 92 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 9c8a49ac060..1b8e32a3f31 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -48,13 +48,7 @@ extern ULONG_PTR KERNEL_BASE; * On UP machines, we don't actually have a spinlock, we merely raise * IRQL to DPC level. */ -#ifndef CONFIG_SMP -#define KeInitializeDispatcher() -#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel(); -#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql); -#define KeAcquireDispatcherDatabaseLockAtDpcLevel() -#define KeReleaseDispatcherDatabaseLockFromDpcLevel() -#else +#ifdef CONFIG_SMP #define KeInitializeDispatcher() KeInitializeSpinLock(&DispatcherDatabaseLock); #define KeAcquireDispatcherDatabaseLock() KfAcquireSpinLock(&DispatcherDatabaseLock); #define KeAcquireDispatcherDatabaseLockAtDpcLevel() \ @@ -64,6 +58,12 @@ extern ULONG_PTR KERNEL_BASE; #define KeReleaseDispatcherDatabaseLock(OldIrql) \ KeReleaseSpinLockFromDpcLevel(&DispatcherDatabaseLock); \ KiExitDispatcher(OldIrql); +#else +#define KeInitializeDispatcher() +#define KeAcquireDispatcherDatabaseLock() KeRaiseIrqlToDpcLevel(); +#define KeReleaseDispatcherDatabaseLock(OldIrql) KiExitDispatcher(OldIrql); +#define KeAcquireDispatcherDatabaseLockAtDpcLevel() +#define KeReleaseDispatcherDatabaseLockFromDpcLevel() #endif /* The following macro initializes a dispatcher object's header */ @@ -232,14 +232,11 @@ VOID STDCALL KiDispatchThread(ULONG NewThreadStatus); -/* Puts a Thread into a block state. */ -VOID -STDCALL -KiBlockThread( - PNTSTATUS Status, - UCHAR Alertable, - ULONG WaitMode, - UCHAR WaitReason +/* Finds a new thread to run */ +NTSTATUS +NTAPI +KiSwapThread( + VOID ); /* Removes a thread out of a block state. */ diff --git a/reactos/ntoskrnl/ke/gate.c b/reactos/ntoskrnl/ke/gate.c index 6530667b7b6..228ed3cd31a 100644 --- a/reactos/ntoskrnl/ke/gate.c +++ b/reactos/ntoskrnl/ke/gate.c @@ -78,12 +78,15 @@ KeWaitForGate(PKGATE Gate, KiWakeQueue(CurrentThread->Queue); } - /* Block the Thread */ - DPRINT("Blocking the Thread: %x\n", CurrentThread); - KiBlockThread(&Status, - CurrentThread->Alertable, - WaitMode, - WaitReason); + /* Setup the wait information */ + CurrentThread->WaitMode = WaitMode; + CurrentThread->WaitReason = WaitReason; + CurrentThread->WaitTime = 0; + CurrentThread->State = Waiting; + + /* Find a new thread to run */ + DPRINT("Swapping threads\n"); + Status = KiSwapThread(); /* Check if we were executing an APC */ if (Status != STATUS_KERNEL_APC) return; diff --git a/reactos/ntoskrnl/ke/kthread.c b/reactos/ntoskrnl/ke/kthread.c index b473e476335..57c775cb348 100644 --- a/reactos/ntoskrnl/ke/kthread.c +++ b/reactos/ntoskrnl/ke/kthread.c @@ -172,48 +172,22 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus) KEBUGCHECK(0); } -VOID -STDCALL -KiBlockThread(PNTSTATUS Status, - UCHAR Alertable, - ULONG WaitMode, - UCHAR WaitReason) +NTSTATUS +NTAPI +KiSwapThread(VOID) { - PKTHREAD Thread = KeGetCurrentThread(); - PKWAIT_BLOCK WaitBlock; - - if (Thread->ApcState.KernelApcPending) { - - DPRINT("Dispatching Thread as ready (APC!)\n"); - - /* Remove Waits */ - WaitBlock = Thread->WaitBlockList; - do { - RemoveEntryList (&WaitBlock->WaitListEntry); - WaitBlock = WaitBlock->NextWaitBlock; - } while (WaitBlock != Thread->WaitBlockList); - Thread->WaitBlockList = NULL; - - /* Dispatch it and return status */ - KiDispatchThreadNoLock (Ready); - if (Status != NULL) *Status = STATUS_KERNEL_APC; - - } else { + PKTHREAD CurrentThread = KeGetCurrentThread(); - /* Set the Thread Data as Requested */ - DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus); - Thread->Alertable = Alertable; - Thread->WaitMode = (UCHAR)WaitMode; - Thread->WaitReason = WaitReason; + /* Find a new thread to run */ + DPRINT("Dispatching Thread as blocked\n"); + KiDispatchThreadNoLock(Waiting); - /* Dispatch it and return status */ - KiDispatchThreadNoLock(Waiting); - DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus); - if (Status != NULL) *Status = Thread->WaitStatus; - } + /* Lower IRQL back */ + DPRINT("Lowering IRQL \n"); + KfLowerIrql(CurrentThread->WaitIrql); - DPRINT("Releasing Dispatcher Lock\n"); - KfLowerIrql(Thread->WaitIrql); + /* Return the wait status */ + return CurrentThread->WaitStatus; } VOID diff --git a/reactos/ntoskrnl/ke/queue.c b/reactos/ntoskrnl/ke/queue.c index 53d451a50c6..8883a35cd24 100644 --- a/reactos/ntoskrnl/ke/queue.c +++ b/reactos/ntoskrnl/ke/queue.c @@ -286,12 +286,16 @@ KeRemoveQueue(IN PKQUEUE Queue, InsertTailList(&Queue->Header.WaitListHead, &WaitBlock->WaitListEntry); - /* Block the Thread */ - DPRINT("Blocking the Thread: %x %x!\n", KeGetCurrentThread(), Thread); - KiBlockThread(&Status, - FALSE, - WaitMode, - WrQueue); + /* Setup the wait information */ + Thread->WaitMode = WaitMode; + Thread->WaitReason = WrQueue; + Thread->Alertable = FALSE; + Thread->WaitTime = 0; + Thread->State = Waiting; + + /* Find a new thread to run */ + DPRINT("Swapping threads\n"); + Status = KiSwapThread(); /* Reset the wait reason */ Thread->WaitReason = 0; diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index fad80d9c993..2430d30afbd 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -106,7 +106,6 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, PKTIMER ThreadTimer; PKTHREAD CurrentThread = KeGetCurrentThread(); NTSTATUS Status; - DPRINT("Entering KeDelayExecutionThread\n"); /* Check if the lock is already held */ @@ -129,6 +128,15 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, /* Start Wait Loop */ do { + /* Check if a kernel APC is pending and we were below APC_LEVEL */ + if ((CurrentThread->ApcState.KernelApcPending) && + (CurrentThread->WaitIrql < APC_LEVEL)) + { + /* Unlock the dispatcher */ + KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql); + goto SkipWait; + } + /* Chceck if we can do an alertable wait, if requested */ if (KiCheckAlertability(Alertable, CurrentThread, WaitMode, &Status)) break; @@ -162,13 +170,16 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, KiWakeQueue(CurrentThread->Queue); } - /* Block the Thread */ - DPRINT("Blocking the Thread: %d, %d, %x\n", - Alertable, WaitMode, KeGetCurrentThread()); - KiBlockThread(&Status, - Alertable, - WaitMode, - DelayExecution); + /* Setup the wait information */ + CurrentThread->Alertable = Alertable; + CurrentThread->WaitMode = WaitMode; + CurrentThread->WaitReason = DelayExecution; + CurrentThread->WaitTime = 0; + CurrentThread->State = Waiting; + + /* Find a new thread to run */ + DPRINT("Swapping threads\n"); + Status = KiSwapThread(); /* Check if we were executing an APC or if we timed out */ if (Status != STATUS_KERNEL_APC) @@ -180,7 +191,11 @@ KeDelayExecutionThread(KPROCESSOR_MODE WaitMode, return Status; } - DPRINT("Looping Again\n"); // FIXME: Need to modify interval + /* FIXME: Fixup interval */ + + /* Acquire again the lock */ +SkipWait: + DPRINT("Looping again\n"); CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock(); } while (TRUE); @@ -241,6 +256,15 @@ KeWaitForSingleObject(PVOID Object, /* Start the actual Loop */ do { + /* Check if a kernel APC is pending and we were below APC_LEVEL */ + if ((CurrentThread->ApcState.KernelApcPending) && + (CurrentThread->WaitIrql < APC_LEVEL)) + { + /* Unlock the dispatcher */ + KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql); + goto SkipWait; + } + /* Get the current Wait Status */ WaitStatus = CurrentThread->WaitStatus; @@ -344,13 +368,16 @@ KeWaitForSingleObject(PVOID Object, KiWakeQueue(CurrentThread->Queue); } - /* Block the Thread */ - DPRINT("Blocking the Thread: %d, %d, %d, %x\n", - Alertable, WaitMode, WaitReason, KeGetCurrentThread()); - KiBlockThread(&Status, - Alertable, - WaitMode, - (UCHAR)WaitReason); + /* Setup the wait information */ + CurrentThread->Alertable = Alertable; + CurrentThread->WaitMode = WaitMode; + CurrentThread->WaitReason = WaitReason; + CurrentThread->WaitTime = 0; + CurrentThread->State = Waiting; + + /* Find a new thread to run */ + DPRINT("Swapping threads\n"); + Status = KiSwapThread(); /* Check if we were executing an APC */ if (Status != STATUS_KERNEL_APC) @@ -359,8 +386,15 @@ KeWaitForSingleObject(PVOID Object, return Status; } - /* Loop again and acquire the dispatcher lock */ - DPRINT("Looping Again\n"); // FIXME: Change interval + /* Check if we had a timeout */ + if (Timeout) + { + /* FIXME: Fixup interval */ + } + + /* Acquire again the lock */ +SkipWait: + DPRINT("Looping again\n"); CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock(); } while (TRUE); @@ -443,6 +477,15 @@ KeWaitForMultipleObjects(ULONG Count, /* Start the actual Loop */ do { + /* Check if a kernel APC is pending and we were below APC_LEVEL */ + if ((CurrentThread->ApcState.KernelApcPending) && + (CurrentThread->WaitIrql < APC_LEVEL)) + { + /* Unlock the dispatcher */ + KeReleaseDispatcherDatabaseLock(CurrentThread->WaitIrql); + goto SkipWait; + } + /* Get the current Wait Status */ WaitStatus = CurrentThread->WaitStatus; @@ -612,13 +655,16 @@ KeWaitForMultipleObjects(ULONG Count, KiWakeQueue(CurrentThread->Queue); } - /* Block the Thread */ - DPRINT("Blocking the Thread: %d, %d, %d, %x\n", - Alertable, WaitMode, WaitReason, KeGetCurrentThread()); - KiBlockThread(&Status, - Alertable, - WaitMode, - (UCHAR)WaitReason); + /* Setup the wait information */ + CurrentThread->Alertable = Alertable; + CurrentThread->WaitMode = WaitMode; + CurrentThread->WaitReason = WaitReason; + CurrentThread->WaitTime = 0; + CurrentThread->State = Waiting; + + /* Find a new thread to run */ + DPRINT("Swapping threads\n"); + Status = KiSwapThread(); /* Check if we were executing an APC */ DPRINT("Thread is back\n"); @@ -628,8 +674,15 @@ KeWaitForMultipleObjects(ULONG Count, return Status; } - /* Loop again and re-acquire the dispatcher lock */ - DPRINT("Looping Again\n"); // FIXME: Fix-up the interval */ + /* Check if we had a timeout */ + if (Timeout) + { + /* FIXME: Fixup interval */ + } + + /* Acquire again the lock */ +SkipWait: + DPRINT("Looping again\n"); CurrentThread->WaitIrql = KeAcquireDispatcherDatabaseLock(); } while (TRUE); -- 2.17.1