Author: ion
Date: Wed Jan 17 04:56:15 2007
New Revision: 25491
URL:
http://svn.reactos.org/svn/reactos?rev=25491&view=rev
Log:
- 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.
Modified:
trunk/reactos/ntoskrnl/include/internal/ke.h
trunk/reactos/ntoskrnl/include/internal/ke_x.h
trunk/reactos/ntoskrnl/ke/dpc.c
trunk/reactos/ntoskrnl/ke/thrdobj.c
trunk/reactos/ntoskrnl/ke/thrdschd.c
trunk/reactos/ntoskrnl/ke/wait.c
Modified: trunk/reactos/ntoskrnl/include/internal/ke.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke.h Wed Jan 17 04:56:15 2007
@@ -223,15 +223,14 @@
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
);
Modified: trunk/reactos/ntoskrnl/include/internal/ke_x.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/ke_x.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/ke_x.h Wed Jan 17 04:56:15 2007
@@ -1259,12 +1259,12 @@
{
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 @@
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 @@
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));
Modified: trunk/reactos/ntoskrnl/ke/dpc.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/dpc.c?rev=2549…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/dpc.c (original)
+++ trunk/reactos/ntoskrnl/ke/dpc.c Wed Jan 17 04:56:15 2007
@@ -70,7 +70,22 @@
/* 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,13 +109,8 @@
/* 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 @@
}
/* 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];
Modified: trunk/reactos/ntoskrnl/ke/thrdobj.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/thrdobj.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/thrdobj.c (original)
+++ trunk/reactos/ntoskrnl/ke/thrdobj.c Wed Jan 17 04:56:15 2007
@@ -1252,7 +1252,6 @@
{
KIRQL OldIrql;
KAFFINITY OldAffinity;
- BOOLEAN Released;
ASSERT_THREAD(Thread);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
@@ -1260,21 +1259,10 @@
OldIrql = KiAcquireDispatcherLock();
/* Call the internal function */
- OldAffinity = KiSetAffinityThread(Thread, Affinity, &Released);
-
- /* Check if lock was released */
- if (!Released)
- {
- /* Release the dispatcher database */
- KiReleaseDispatcherLock(OldIrql);
- }
- else
- {
- /* Lower IRQL only */
- KeLowerIrql(OldIrql);
- }
-
- /* Return old affinity */
+ OldAffinity = KiSetAffinityThread(Thread, Affinity);
+
+ /* Release the dispatcher database and return old affinity */
+ KiReleaseDispatcherLock(OldIrql);
return OldAffinity;
}
Modified: trunk/reactos/ntoskrnl/ke/thrdschd.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/thrdschd.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/thrdschd.c (original)
+++ trunk/reactos/ntoskrnl/ke/thrdschd.c Wed Jan 17 04:56:15 2007
@@ -23,17 +23,6 @@
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,
PKTHREAD Thread)
{
@@ -166,6 +155,40 @@
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 @@
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 @@
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 @@
}
VOID
-STDCALL
+NTAPI
KiAdjustQuantumThread(IN PKTHREAD Thread)
{
PKPRCB Prcb = KeGetCurrentPrcb();
@@ -275,10 +302,14 @@
/* 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 @@
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)
- {
- /* Set it */
- Thread->Priority = (SCHAR)Priority;
-
- /* Choose action based on thread's state */
- if (Thread->State == Ready)
+ if (Thread->Priority != Priority)
+ {
+ /* 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)
- {
- /* 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)
- {
- /* Found a thread, is it us? */
- if (Thread == KeGetCurrentThread())
+ /* Choose action based on thread's state */
+ if (Thread->State == Ready)
+ {
+ /* Make sure we're not on the ready queue */
+ if (Thread->ProcessReadyQueue)
+ {
+ /* 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++)
+ /* 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);
+
+ /* 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)
{
- /* Get the PCR for this CPU */
- Pcr = (PKPCR)(KPCR_BASE + i * PAGE_SIZE);
-
- /* Reschedule if the new one is already on a CPU */
- if (Pcr->Prcb->CurrentThread == Thread)
+ /* 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 @@
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);
- }
- }
- }
-
- *Released = FALSE;
+ /* Check if system affinity is disabled */
+ if (!Thread->SystemAffinityActive)
+ {
+ /* FIXME: TODO */
+ DPRINT1("Affinity support disabled!\n");
+ }
+
+ /* Return the old affinity */
return OldAffinity;
}
Modified: trunk/reactos/ntoskrnl/ke/wait.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/wait.c?rev=254…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/wait.c (original)
+++ trunk/reactos/ntoskrnl/ke/wait.c Wed Jan 17 04:56:15 2007
@@ -182,10 +182,6 @@
/* 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);