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