- 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)
{
/* 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

View 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);
}
else
{
/* Otherwise just release the lock */
KiReleaseDispatcherLockFromDpcLevel();
/* 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;
}
/* Lower irql back */
/* 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);
}