- Add the actual missing code to KiQuantumEnd. It's asserted to make sure it'll never...
authorAlex Ionescu <aionescu@gmail.com>
Mon, 11 Sep 2006 05:26:38 +0000 (05:26 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Mon, 11 Sep 2006 05:26:38 +0000 (05:26 +0000)
- Add KiExitDispatcher from my new scheduler code. Same as KiQuantumEnd, added an assertion to make sure it doesn't enter in code paths that shouldn't yet happen.

svn path=/trunk/; revision=24061

reactos/ntoskrnl/ke/dpc.c
reactos/ntoskrnl/ke/wait.c

index e6c1bd3..926a874 100644 (file)
@@ -71,7 +71,6 @@ KiQuantumEnd(VOID)
             if (!Prcb->NextThread)
             {
                 /* FIXME: TODO. Add code from new scheduler */
-                NextThread = NULL;
             }
             else
             {
@@ -102,6 +101,32 @@ KiQuantumEnd(VOID)
     /* This shouldn't happen on ROS yet */
     DPRINT1("The impossible happened - Tell Alex\n");
     ASSERT(FALSE);
+
+    /* Get the next thread now */
+    NextThread = Prcb->NextThread;
+
+    /* Set current thread's swap busy to true */
+    KiSetThreadSwapBusy(Thread);
+
+    /* Switch threads in PRCB */
+    Prcb->NextThread = NULL;
+    Prcb->CurrentThread = NextThread;
+
+    /* Set thread to running and the switch reason to Quantum End */
+    NextThread->State = Running;
+    Thread->WaitReason = WrQuantumEnd;
+
+    /* Queue it on the ready lists */
+    KxQueueReadyThread(Thread, Prcb);
+
+    /* Set wait IRQL to APC_LEVEL */
+    Thread->WaitIrql = APC_LEVEL;
+
+    /* Swap threads */
+    KiSwapContext(Thread, NextThread);
+
+    /* Lower IRQL back to DISPATCH_LEVEL */
+    KeLowerIrql(DISPATCH_LEVEL);
 }
 
 VOID
index 38eac34..91935a2 100644 (file)
@@ -236,26 +236,85 @@ KiAcquireFastMutex(IN PFAST_MUTEX FastMutex)
                           NULL);
 }
 
+//
+// This routine exits the dispatcher after a compatible operation and
+// swaps the context to the next scheduled thread on the current CPU if
+// one is available.
+//
+// It does NOT attempt to scan for a new thread to schedule.
+//
 VOID
 FASTCALL
 KiExitDispatcher(IN KIRQL OldIrql)
 {
-    /* Check if it's the idle thread */
-    if (!(KeIsExecutingDpc()) &&
-        (OldIrql < DISPATCH_LEVEL) &&
-        (KeGetCurrentThread()) &&
-        (KeGetCurrentThread() == KeGetCurrentPrcb()->IdleThread))
+    PKPRCB Prcb = KeGetCurrentPrcb();
+    PKTHREAD Thread, NextThread;
+    BOOLEAN PendingApc;
+
+    /* Make sure we're at synchronization level */
+    ASSERT_IRQL(SYNCH_LEVEL);
+
+    /* Check if we have deferred threads */
+    KiCheckDeferredReadyList(Prcb);
+
+    /* Check if we were called at dispatcher level or higher */
+    if (OldIrql >= DISPATCH_LEVEL)
     {
-        /* Dispatch a new thread */
-        KiDispatchThreadNoLock(Ready);
+        /* Check if we have a thread to schedule, and that no DPC is active */
+        if ((Prcb->NextThread) && !(Prcb->DpcRoutineActive))
+        {
+            /* Request DPC interrupt */
+            HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
+        }
+
+        /* Lower IRQL and exit */
+        goto Quickie;
     }
-    else
+
+    /* Make sure there's a new thread scheduled */
+    if (!Prcb->NextThread) goto Quickie;
+
+    /* This shouldn't happen on ROS yet */
+    DPRINT1("The impossible happened - Tell Alex\n");
+    ASSERT(FALSE);
+
+    /* Lock the PRCB */
+    KiAcquirePrcbLock(Prcb);
+
+    /* Get the next and current threads now */
+    NextThread = Prcb->NextThread;
+    Thread = Prcb->CurrentThread;
+
+    /* Set current thread's swap busy to true */
+    KiSetThreadSwapBusy(Thread);
+
+    /* Switch threads in PRCB */
+    Prcb->NextThread = NULL;
+    Prcb->CurrentThread = NextThread;
+
+    /* Set thread to running */
+    NextThread->State = Running;
+
+    /* Queue it on the ready lists */
+    KxQueueReadyThread(Thread, Prcb);
+
+    /* Set wait IRQL */
+    Thread->WaitIrql = OldIrql;
+
+    /* Swap threads and check if APCs were pending */
+    PendingApc = KiSwapContext(Thread, NextThread);
+    if (PendingApc)
     {
-        /* Otherwise just release the lock */
-        KiReleaseDispatcherLockFromDpcLevel();
+        /* Lower only to APC */
+        KeLowerIrql(APC_LEVEL);
+
+        /* Deliver APCs */
+        KiDeliverApc(KernelMode, NULL, NULL);
+        ASSERT(OldIrql == PASSIVE_LEVEL);
     }
 
-    /* Lower irql back */
+    /* Lower IRQl back */
+Quickie:
     KeLowerIrql(OldIrql);
 }