- Add the actual missing code to KiQuantumEnd. It's asserted to make sure it'll never execute (yet).

- 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
This commit is contained in:
Alex Ionescu 2006-09-11 05:26:38 +00:00
parent 6c853c9c32
commit a0fac81cfd
2 changed files with 98 additions and 14 deletions

View file

@ -71,7 +71,6 @@ KiQuantumEnd(VOID)
if (!Prcb->NextThread) if (!Prcb->NextThread)
{ {
/* FIXME: TODO. Add code from new scheduler */ /* FIXME: TODO. Add code from new scheduler */
NextThread = NULL;
} }
else else
{ {
@ -102,6 +101,32 @@ KiQuantumEnd(VOID)
/* This shouldn't happen on ROS yet */ /* This shouldn't happen on ROS yet */
DPRINT1("The impossible happened - Tell Alex\n"); DPRINT1("The impossible happened - Tell Alex\n");
ASSERT(FALSE); 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 VOID

View file

@ -236,26 +236,85 @@ KiAcquireFastMutex(IN PFAST_MUTEX FastMutex)
NULL); 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 VOID
FASTCALL FASTCALL
KiExitDispatcher(IN KIRQL OldIrql) KiExitDispatcher(IN KIRQL OldIrql)
{ {
/* Check if it's the idle thread */ PKPRCB Prcb = KeGetCurrentPrcb();
if (!(KeIsExecutingDpc()) && PKTHREAD Thread, NextThread;
(OldIrql < DISPATCH_LEVEL) && BOOLEAN PendingApc;
(KeGetCurrentThread()) &&
(KeGetCurrentThread() == KeGetCurrentPrcb()->IdleThread)) /* 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 */ /* Check if we have a thread to schedule, and that no DPC is active */
KiDispatchThreadNoLock(Ready); if ((Prcb->NextThread) && !(Prcb->DpcRoutineActive))
}
else
{ {
/* Otherwise just release the lock */ /* Request DPC interrupt */
KiReleaseDispatcherLockFromDpcLevel(); HalRequestSoftwareInterrupt(DISPATCH_LEVEL);
} }
/* Lower irql back */ /* Lower IRQL and exit */
goto Quickie;
}
/* 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)
{
/* Lower only to APC */
KeLowerIrql(APC_LEVEL);
/* Deliver APCs */
KiDeliverApc(KernelMode, NULL, NULL);
ASSERT(OldIrql == PASSIVE_LEVEL);
}
/* Lower IRQl back */
Quickie:
KeLowerIrql(OldIrql); KeLowerIrql(OldIrql);
} }