- 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. Modified: trunk/reactos/ntoskrnl/include/internal/ke.h Modified: trunk/reactos/ntoskrnl/ke/gate.c Modified: trunk/reactos/ntoskrnl/ke/kthread.c Modified: trunk/reactos/ntoskrnl/ke/queue.c Modified: trunk/reactos/ntoskrnl/ke/wait.c _____
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h --- trunk/reactos/ntoskrnl/include/internal/ke.h 2006-01-06 06:38:47 UTC (rev 20604) +++ trunk/reactos/ntoskrnl/include/internal/ke.h 2006-01-06 08:00:09 UTC (rev 20605) @@ -48,13 +48,7 @@
* 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 @@ #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 @@ 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. */ _____
Modified: trunk/reactos/ntoskrnl/ke/gate.c --- trunk/reactos/ntoskrnl/ke/gate.c 2006-01-06 06:38:47 UTC (rev 20604) +++ trunk/reactos/ntoskrnl/ke/gate.c 2006-01-06 08:00:09 UTC (rev 20605) @@ -78,13 +78,16 @@
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;
_____
Modified: trunk/reactos/ntoskrnl/ke/kthread.c --- trunk/reactos/ntoskrnl/ke/kthread.c 2006-01-06 06:38:47 UTC (rev 20604) +++ trunk/reactos/ntoskrnl/ke/kthread.c 2006-01-06 08:00:09 UTC (rev 20605) @@ -172,48 +172,22 @@
KEBUGCHECK(0); }
-VOID -STDCALL -KiBlockThread(PNTSTATUS Status, - UCHAR Alertable, - ULONG WaitMode, - UCHAR WaitReason) +NTSTATUS +NTAPI +KiSwapThread(VOID) { - PKTHREAD Thread = KeGetCurrentThread(); - PKWAIT_BLOCK WaitBlock; + PKTHREAD CurrentThread = KeGetCurrentThread();
- if (Thread->ApcState.KernelApcPending) { + /* Find a new thread to run */ + DPRINT("Dispatching Thread as blocked\n"); + KiDispatchThreadNoLock(Waiting);
- DPRINT("Dispatching Thread as ready (APC!)\n"); + /* Lower IRQL back */ + DPRINT("Lowering IRQL \n"); + KfLowerIrql(CurrentThread->WaitIrql);
- /* 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 { - - /* 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; - - /* Dispatch it and return status */ - KiDispatchThreadNoLock(Waiting); - DPRINT("Dispatching Thread as blocked: %d\n", Thread->WaitStatus); - if (Status != NULL) *Status = Thread->WaitStatus; - } - - DPRINT("Releasing Dispatcher Lock\n"); - KfLowerIrql(Thread->WaitIrql); + /* Return the wait status */ + return CurrentThread->WaitStatus; }
VOID _____
Modified: trunk/reactos/ntoskrnl/ke/queue.c --- trunk/reactos/ntoskrnl/ke/queue.c 2006-01-06 06:38:47 UTC (rev 20604) +++ trunk/reactos/ntoskrnl/ke/queue.c 2006-01-06 08:00:09 UTC (rev 20605) @@ -286,13 +286,17 @@
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;
_____
Modified: trunk/reactos/ntoskrnl/ke/wait.c --- trunk/reactos/ntoskrnl/ke/wait.c 2006-01-06 06:38:47 UTC (rev 20604) +++ trunk/reactos/ntoskrnl/ke/wait.c 2006-01-06 08:00:09 UTC (rev 20605) @@ -106,7 +106,6 @@
PKTIMER ThreadTimer; PKTHREAD CurrentThread = KeGetCurrentThread(); NTSTATUS Status; - DPRINT("Entering KeDelayExecutionThread\n");
/* Check if the lock is already held */ @@ -129,6 +128,15 @@ /* 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,14 +170,17 @@ 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 @@ 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 @@ /* 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,14 +368,17 @@ 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 @@ 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 @@ /* 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,14 +655,17 @@ 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"); if (Status != STATUS_KERNEL_APC) @@ -628,8 +674,15 @@ 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);