- 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);