- Simplify KiSelectReadyThread.

- Disable KiSetAffinityThread to do nothing else but change affinity instead of doing re-scheduling (temporary change).
- Cleanup KiQuantumEnd to prepare for new scheduler.
- Fix up a large bug in KeInsertQueueDpc which was making every DPC become a Threaded DPC due to a bad assignment-instead-of-compare.
- Copy KiSelectNextThread for new scheduler branch, without SMT support.
- Fix a bug in KiAdjustQuantumThread under new scheduler.
- Re-implement KiSetPriorityThread under new scheduler, leave hacks for current scheduler support.
- Remove old testing assert from KiExitDispatcher.

svn path=/trunk/; revision=25491
This commit is contained in:
Alex Ionescu 2007-01-17 01:56:15 +00:00
parent c15d054bad
commit c696d66532
6 changed files with 258 additions and 147 deletions

View file

@ -223,15 +223,14 @@ NTAPI
KiDeferredReadyThread(IN PKTHREAD Thread);
KAFFINITY
NTAPI
FASTCALL
KiSetAffinityThread(
IN PKTHREAD Thread,
IN KAFFINITY Affinity,
IN PBOOLEAN Released // hack
IN KAFFINITY Affinity
);
PKTHREAD
NTAPI
FASTCALL
KiSelectNextThread(
IN PKPRCB Prcb
);

View file

@ -1259,12 +1259,12 @@ KiSelectReadyThread(IN KPRIORITY Priority,
{
LONG PriorityMask, PrioritySet, HighPriority;
PLIST_ENTRY ListEntry;
PKTHREAD Thread;
PKTHREAD Thread = NULL;
/* Save the current mask and get the priority set for the CPU */
PriorityMask = Priority;
PrioritySet = Prcb->ReadySummary >> (UCHAR)Priority;
if (!PrioritySet) return NULL;
if (!PrioritySet) goto Quickie;
/* Get the highest priority possible */
BitScanReverse((PULONG)&HighPriority, PrioritySet);
@ -1275,7 +1275,7 @@ KiSelectReadyThread(IN KPRIORITY Priority,
ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[HighPriority]) == FALSE);
/* Get the first thread on the list */
ListEntry = &Prcb->DispatcherReadyListHead[HighPriority];
ListEntry = Prcb->DispatcherReadyListHead[HighPriority].Flink;
Thread = CONTAINING_RECORD(ListEntry, KTHREAD, WaitListEntry);
/* Make sure this thread is here for a reason */
@ -1284,14 +1284,14 @@ KiSelectReadyThread(IN KPRIORITY Priority,
ASSERT(Thread->NextProcessor == Prcb->Number);
/* Remove it from the list */
RemoveEntryList(&Thread->WaitListEntry);
if (IsListEmpty(&Thread->WaitListEntry))
if (RemoveEntryList(&Thread->WaitListEntry))
{
/* The list is empty now, reset the ready summary */
Prcb->ReadySummary ^= PRIORITY_MASK(HighPriority);
}
/* Sanity check and return the thread */
Quickie:
ASSERT((Thread == NULL) ||
(Thread->BasePriority == 0) ||
(Thread->Priority != 0));

View file

@ -70,7 +70,22 @@ KiQuantumEnd(VOID)
/* Check if a new thread is scheduled */
if (!Prcb->NextThread)
{
/* FIXME: TODO. Add code from new scheduler */
#ifdef NEW_SCHEDULER
/* Get a new ready thread */
NextThread = KiSelectReadyThread(Thread->Priority, Prcb);
if (NextThread)
{
/* Found one, set it on standby */
NextThread->Standby;
Prcb->NextThread = NewThread;
}
#else
/* Just leave now */
KiReleasePrcbLock(Prcb);
KeLowerIrql(DISPATCH_LEVEL);
KiDispatchThread(Ready);
return;
#endif
}
else
{
@ -94,14 +109,9 @@ KiQuantumEnd(VOID)
/* Just leave now */
KiReleasePrcbLock(Prcb);
KeLowerIrql(DISPATCH_LEVEL);
KiDispatchThread(Ready); // FIXME: ROS
return;
}
/* This shouldn't happen on ROS yet */
DPRINT1("The impossible happened - Tell Alex\n");
ASSERT(FALSE);
/* Get the next thread now */
NextThread = Prcb->NextThread;
@ -296,7 +306,7 @@ KeInsertQueueDpc(IN PKDPC Dpc,
}
/* Check if this is a threaded DPC and threaded DPCs are enabled */
if ((Dpc->Type = ThreadedDpcObject) && (Prcb->ThreadDpcEnable))
if ((Dpc->Type == ThreadedDpcObject) && (Prcb->ThreadDpcEnable))
{
/* Then use the threaded data */
DpcData = &Prcb->DpcData[DPC_THREADED];

View file

@ -1252,7 +1252,6 @@ KeSetAffinityThread(IN PKTHREAD Thread,
{
KIRQL OldIrql;
KAFFINITY OldAffinity;
BOOLEAN Released;
ASSERT_THREAD(Thread);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
@ -1260,21 +1259,10 @@ KeSetAffinityThread(IN PKTHREAD Thread,
OldIrql = KiAcquireDispatcherLock();
/* Call the internal function */
OldAffinity = KiSetAffinityThread(Thread, Affinity, &Released);
OldAffinity = KiSetAffinityThread(Thread, Affinity);
/* Check if lock was released */
if (!Released)
{
/* Release the dispatcher database */
KiReleaseDispatcherLock(OldIrql);
}
else
{
/* Lower IRQL only */
KeLowerIrql(OldIrql);
}
/* Return old affinity */
/* Release the dispatcher database and return old affinity */
KiReleaseDispatcherLock(OldIrql);
return OldAffinity;
}

View file

@ -21,17 +21,6 @@ ULONG KiIdleSMTSummary;
/* FUNCTIONS *****************************************************************/
static
VOID
KiRequestReschedule(CCHAR Processor)
{
PKPCR Pcr;
Pcr = (PKPCR)(KPCR_BASE + Processor * PAGE_SIZE);
Pcr->Prcb->QuantumEnd = TRUE;
KiIpiSendRequest(1 << Processor, IPI_DPC);
}
static
VOID
KiInsertIntoThreadList(KPRIORITY Priority,
@ -166,6 +155,40 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus)
return FALSE;
}
VOID
NTAPI
KiDeferredReadyThread(IN PKTHREAD Thread)
{
/* FIXME: Not yet implemented */
KEBUGCHECK(0);
}
PKTHREAD
FASTCALL
KiSelectNextThread(IN PKPRCB Prcb)
{
PKTHREAD Thread;
/* Select a ready thread */
Thread = KiSelectReadyThread(0, Prcb);
if (!Thread)
{
/* Didn't find any, get the current idle thread */
Thread = Prcb->IdleThread;
/* Enable idle scheduling */
InterlockedOr(&KiIdleSummary, Prcb->SetMember);
Prcb->IdleSchedule = TRUE;
/* FIXME: SMT support */
}
/* Sanity checks and return the thread */
ASSERT(Thread != NULL);
ASSERT((Thread->BasePriority == 0) || (Thread->Priority != 0));
return Thread;
}
NTSTATUS
FASTCALL
KiSwapThread(IN PKTHREAD CurrentThread,
@ -174,8 +197,12 @@ KiSwapThread(IN PKTHREAD CurrentThread,
BOOLEAN ApcState;
ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL);
#ifdef NEW_SCHEDULER
#else
/* Find a new thread to run */
ApcState = KiDispatchThreadNoLock(Waiting);
#endif
/* Check if we need to deliver APCs */
if (ApcState)
@ -238,7 +265,7 @@ KiReadyThread(IN PKTHREAD Thread)
else
{
/* Insert the thread on the deferred ready list */
#if 0
#ifdef NEW_SCHEDULER
KiInsertDeferredReadyList(Thread);
#else
/* Insert the thread into the thread list */
@ -249,7 +276,7 @@ KiReadyThread(IN PKTHREAD Thread)
}
VOID
STDCALL
NTAPI
KiAdjustQuantumThread(IN PKTHREAD Thread)
{
PKPRCB Prcb = KeGetCurrentPrcb();
@ -275,10 +302,14 @@ KiAdjustQuantumThread(IN PKTHREAD Thread)
/* Check if there's no next thread scheduled */
if (!Prcb->NextThread)
{
/* Select a new thread and set it on standby */
NextThread = KiSelectNextThread(Prcb);
NextThread->State = Standby;
Prcb->NextThread = NextThread;
/* Select a ready thread and check if we found one */
NextThread = KiSelectReadyThread(Thread->Priority, Prcb);
if (NextThread)
{
/* Set it on standby and switch to it */
NextThread->State = Standby;
Prcb->NextThread = NextThread;
}
}
else
{
@ -303,91 +334,213 @@ KiSetPriorityThread(IN PKTHREAD Thread,
IN KPRIORITY Priority,
OUT PBOOLEAN Released)
{
KPRIORITY OldPriority = Thread->Priority;
ULONG Mask;
ULONG i;
PKPCR Pcr;
PKPRCB Prcb;
ULONG Processor;
BOOLEAN RequestInterrupt = FALSE;
KPRIORITY OldPriority;
PKTHREAD NewThread;
ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));
/* Check if priority changed */
if (OldPriority != Priority)
if (Thread->Priority != Priority)
{
/* Set it */
Thread->Priority = (SCHAR)Priority;
/* Choose action based on thread's state */
if (Thread->State == Ready)
/* Loop priority setting in case we need to start over */
for (;;)
{
/* Remove it from the current queue */
KiRemoveFromThreadList(Thread);
/* Re-insert it at its current priority */
KiInsertIntoThreadList(Priority, Thread);
/* Check if the old priority was lower */
if (KeGetCurrentThread()->Priority < Priority)
/* Choose action based on thread's state */
if (Thread->State == Ready)
{
/* Dispatch it immediately */
KiDispatchThreadNoLock(Ready);
*Released = TRUE;
return;
}
}
else if (Thread->State == Running)
{
/* Check if the new priority is lower */
if (Priority < OldPriority)
{
/* Check for threads with a higher priority */
Mask = ~((1 << (Priority + 1)) - 1);
if (PriorityListMask & Mask)
/* Make sure we're not on the ready queue */
if (Thread->ProcessReadyQueue)
{
/* Found a thread, is it us? */
if (Thread == KeGetCurrentThread())
/* Get the PRCB for the thread and lock it */
Processor = Thread->NextProcessor;
Prcb = KiProcessorBlock[Processor];
KiAcquirePrcbLock(Prcb);
/* Make sure the thread is still ready and on this CPU */
if ((Thread->State == Ready) &&
(Thread->NextProcessor == Prcb->Number))
{
/* Dispatch us */
/* Sanity check */
ASSERT((Prcb->ReadySummary &
PRIORITY_MASK(Thread->Priority)));
/* Remove it from the current queue */
#ifdef NEW_SCHEDULER
if (RemoveEntryList(&Thread->WaitListEntry))
{
/* Update the ready summary */
Prcb->ReadySummary ^= PRIORITY_MASK(Thread->Priority);
}
#else
KiRemoveFromThreadList(Thread);
#endif
/* Update priority */
Thread->Priority = (SCHAR)Priority;
/* Re-insert it at its current priority */
#ifndef NEW_SCHEDULER
KiInsertIntoThreadList(Priority, Thread);
KiDispatchThreadNoLock(Ready);
*Released = TRUE;
return;
}
#else
KiInsertDeferredReadyList(Thread);
#endif
/* Release the PRCB Lock */
KiReleasePrcbLock(Prcb);
}
else
{
/* Loop every CPU */
for (i = 0; i < KeNumberProcessors; i++)
{
/* Get the PCR for this CPU */
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
/* Release the lock and loop again */
KEBUGCHECK(0);
KiReleasePrcbLock(Prcb);
continue;
}
}
else
{
/* It's already on the ready queue, just update priority */
Thread->Priority = (SCHAR)Priority;
}
}
else if (Thread->State == Standby)
{
/* Get the PRCB for the thread and lock it */
KEBUGCHECK(0);
Processor = Thread->NextProcessor;
Prcb = KiProcessorBlock[Processor];
KiAcquirePrcbLock(Prcb);
/* Reschedule if the new one is already on a CPU */
if (Pcr->Prcb->CurrentThread == Thread)
/* Check if we're still the next thread to run */
if (Thread == Prcb->NextThread)
{
/* Get the old priority and update ours */
OldPriority = Thread->Priority;
Thread->Priority = (SCHAR)Priority;
/* Check if there was a change */
if (Priority < OldPriority)
{
/* Find a new thread */
NewThread = KiSelectReadyThread(Priority + 1, Prcb);
if (NewThread)
{
/* Found a new one, set it on standby */
NewThread->State = Standby;
Prcb->NextThread = NewThread;
/* Dispatch our thread */
KiInsertDeferredReadyList(Thread);
}
}
/* Release the PRCB lock */
KiReleasePrcbLock(Prcb);
}
else
{
/* Release the lock and try again */
KiReleasePrcbLock(Prcb);
continue;
}
}
else if (Thread->State == Running)
{
/* Get the PRCB for the thread and lock it */
Processor = Thread->NextProcessor;
Prcb = KiProcessorBlock[Processor];
KiAcquirePrcbLock(Prcb);
/* Check if we're still the current thread running */
if (Thread == Prcb->CurrentThread)
{
/* Get the old priority and update ours */
OldPriority = Thread->Priority;
Thread->Priority = (SCHAR)Priority;
/* Check if there was a change and there's no new thread */
if ((Priority < OldPriority) && !(Prcb->NextThread))
{
#ifdef NEW_SCHEDULER
/* Find a new thread */
NewThread = KiSelectReadyThread(Priority + 1, Prcb);
if (NewThread)
{
/* Found a new one, set it on standby */
NewThread->State = Standby;
Prcb->NextThread = NewThread;
/* Request an interrupt */
RequestInterrupt = TRUE;
}
#else
/* Check for threads with a higher priority */
if (PriorityListMask & ~((1 << (Priority + 1)) - 1))
{
/* Found a thread, is it us? */
if (Thread == KeGetCurrentThread())
{
KiReleaseDispatcherLockFromDpcLevel();
KiRequestReschedule(i);
/* Dispatch us */
KiDispatchThreadNoLock(Ready);
*Released = TRUE;
return;
}
}
#endif
}
/* Release the lock and check if we need an interrupt */
KiReleasePrcbLock(Prcb);
if (RequestInterrupt)
{
/* Check if we're running on another CPU */
if (KeGetCurrentProcessorNumber() != Processor)
{
/* We are, send an IPI */
KiIpiSendRequest(AFFINITY_MASK(Processor), IPI_DPC);
}
}
}
else
{
/* Thread changed, release lock and restart */
KiReleasePrcbLock(Prcb);
continue;
}
}
else if (Thread->State == DeferredReady)
{
/* FIXME: TODO */
DPRINT1("Deferred state not yet supported\n");
KEBUGCHECK(0);
}
else
{
/* Any other state, just change priority */
Thread->Priority = (SCHAR)Priority;
}
/* If we got here, then thread state was consistent, so bail out */
break;
}
}
/* Return to caller */
*Released = FALSE;
return;
}
KAFFINITY
NTAPI
FASTCALL
KiSetAffinityThread(IN PKTHREAD Thread,
IN KAFFINITY Affinity,
PBOOLEAN Released)
IN KAFFINITY Affinity)
{
KAFFINITY OldAffinity;
ULONG ProcessorMask;
CCHAR i;
PKPCR Pcr;
/* Get the current affinity */
OldAffinity = Thread->UserAffinity;
/* Make sure that the affinity is valid */
if (((Affinity & Thread->ApcState.Process->Affinity) != (Affinity)) ||
@ -397,52 +550,17 @@ KiSetAffinityThread(IN PKTHREAD Thread,
KeBugCheck(INVALID_AFFINITY_SET);
}
/* Get the old affinity */
OldAffinity = Thread->UserAffinity;
/* Update the new affinity */
Thread->UserAffinity = Affinity;
if (Thread->SystemAffinityActive == FALSE) {
Thread->Affinity = Affinity;
if (Thread->State == Running) {
ProcessorMask = 1 << KeGetCurrentProcessorNumber();
if (Thread == KeGetCurrentThread()) {
if (!(Affinity & ProcessorMask)) {
KiDispatchThreadNoLock(Ready);
*Released = TRUE;
return OldAffinity;
}
} else {
for (i = 0; i < KeNumberProcessors; i++) {
Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
if (Pcr->Prcb->CurrentThread == Thread) {
if (!(Affinity & ProcessorMask)) {
KiReleaseDispatcherLockFromDpcLevel();
KiRequestReschedule(i);
*Released = TRUE;
return OldAffinity;
}
break;
}
}
ASSERT (i < KeNumberProcessors);
}
}
/* Check if system affinity is disabled */
if (!Thread->SystemAffinityActive)
{
/* FIXME: TODO */
DPRINT1("Affinity support disabled!\n");
}
*Released = FALSE;
/* Return the old affinity */
return OldAffinity;
}

View file

@ -183,10 +183,6 @@ KiExitDispatcher(IN KIRQL OldIrql)
/* 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);