From 8be76ffcb33ac8754b796f5ddc835f330c93472e Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Wed, 17 Jan 2007 21:53:45 +0000 Subject: [PATCH] - Remove hack from KiSetPriorityThread. Now it doesn't dispatch threads anymore, but this cleans up the IRQL/Dispatcher hack (it will still insert the higher priority thread in the right queue though, so there's not much visible change, just that priorities suck a bit more -- but this is temporary). - Guard some more code with #ifdef NEW_SCHEDULER. - Fix bugs in KiDispatchInterrupt. - Use PRCB fields instead of PriorityListHead/PriorityListMask to reduces number of code changes between NEW_SCHEDULER and old. - Fully implement KiDeferredReadyThread, but only for Uni-Processor systems. Supports unwait boosts as well as lock boosts. Not yet used. - Implement NEW_SCHEDULER version of KiSwapThread and NtYieldExecution. svn path=/trunk/; revision=25502 --- reactos/ntoskrnl/include/internal/ke.h | 5 +- reactos/ntoskrnl/ke/dpc.c | 4 +- reactos/ntoskrnl/ke/i386/ctxswitch.S | 2 + reactos/ntoskrnl/ke/i386/trap.s | 6 +- reactos/ntoskrnl/ke/process.c | 7 +- reactos/ntoskrnl/ke/thrdobj.c | 34 +- reactos/ntoskrnl/ke/thrdschd.c | 453 +++++++++++++++++++++---- reactos/ntoskrnl/ps/psmgr.c | 7 - 8 files changed, 413 insertions(+), 105 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index d8f38c0b848..985ffda0d84 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -449,11 +449,10 @@ NTAPI KeQueryBasePriorityThread(IN PKTHREAD Thread); VOID -NTAPI +FASTCALL KiSetPriorityThread( IN PKTHREAD Thread, - IN KPRIORITY Priority, - IN PBOOLEAN Released // hack + IN KPRIORITY Priority ); BOOLEAN diff --git a/reactos/ntoskrnl/ke/dpc.c b/reactos/ntoskrnl/ke/dpc.c index 32244cc06d0..a0760762143 100644 --- a/reactos/ntoskrnl/ke/dpc.c +++ b/reactos/ntoskrnl/ke/dpc.c @@ -76,8 +76,8 @@ KiQuantumEnd(VOID) if (NextThread) { /* Found one, set it on standby */ - NextThread->Standby; - Prcb->NextThread = NewThread; + NextThread->State = Standby; + Prcb->NextThread = NextThread; } #else /* Just leave now */ diff --git a/reactos/ntoskrnl/ke/i386/ctxswitch.S b/reactos/ntoskrnl/ke/i386/ctxswitch.S index b84a84ee083..9d2d30e34e2 100644 --- a/reactos/ntoskrnl/ke/i386/ctxswitch.S +++ b/reactos/ntoskrnl/ke/i386/ctxswitch.S @@ -643,8 +643,10 @@ MainLoop: call @KfLowerIrql@4 CheckSchedule: +#ifndef NEW_SCHEDULER /* FIXME: ROS HACK */ call _NtYieldExecution@0 +#endif /* Check if a next thread is queued */ cmp dword ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0 diff --git a/reactos/ntoskrnl/ke/i386/trap.s b/reactos/ntoskrnl/ke/i386/trap.s index eaddb11679c..9ec54bae656 100644 --- a/reactos/ntoskrnl/ke/i386/trap.s +++ b/reactos/ntoskrnl/ke/i386/trap.s @@ -2099,13 +2099,13 @@ CheckQuantum: /* Check if we have a thread to swap to */ cmp byte ptr [ebx+KPCR_PRCB_NEXT_THREAD], 0 - jmp Return + je Return /* Make space on the stack to save registers */ sub esp, 3 * 4 mov [esp+8], esi - mov [esi+4], edi - mov [esi+0], ebp + mov [esp+4], edi + mov [esp+0], ebp /* Get the current thread */ mov edi, [ebx+KPCR_CURRENT_THREAD] diff --git a/reactos/ntoskrnl/ke/process.c b/reactos/ntoskrnl/ke/process.c index b6280e3bacd..64e2d0de353 100644 --- a/reactos/ntoskrnl/ke/process.c +++ b/reactos/ntoskrnl/ke/process.c @@ -289,7 +289,6 @@ KeSetPriorityAndQuantumProcess(IN PKPROCESS Process, PLIST_ENTRY NextEntry, ListHead; KPRIORITY NewPriority, OldPriority; PKTHREAD Thread; - BOOLEAN Released; ASSERT_PROCESS(Process); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); @@ -368,7 +367,7 @@ KeSetPriorityAndQuantumProcess(IN PKPROCESS Process, /* Disable decrements and update priority */ Thread->PriorityDecrement = 0; - KiSetPriorityThread(Thread, NewPriority, &Released); + KiSetPriorityThread(Thread, NewPriority); } /* Release the thread lock */ @@ -430,7 +429,7 @@ KeSetPriorityAndQuantumProcess(IN PKPROCESS Process, /* Disable decrements and update priority */ Thread->PriorityDecrement = 0; - KiSetPriorityThread(Thread, NewPriority, &Released); + KiSetPriorityThread(Thread, NewPriority); } /* Release the thread lock */ @@ -442,7 +441,7 @@ KeSetPriorityAndQuantumProcess(IN PKPROCESS Process, } /* Release Dispatcher Database */ - if (!Released) KiReleaseDispatcherLockFromDpcLevel(); + KiReleaseDispatcherLockFromDpcLevel(); /* Release the process lock */ KiReleaseProcessLockFromDpcLevel(&ProcessLock); diff --git a/reactos/ntoskrnl/ke/thrdobj.c b/reactos/ntoskrnl/ke/thrdobj.c index c1c9ad5b907..5377642449f 100644 --- a/reactos/ntoskrnl/ke/thrdobj.c +++ b/reactos/ntoskrnl/ke/thrdobj.c @@ -1126,7 +1126,6 @@ KeSetBasePriorityThread(IN PKTHREAD Thread, KPRIORITY OldBasePriority, Priority, BasePriority; LONG OldIncrement; PKPROCESS Process; - BOOLEAN Released = FALSE; ASSERT_THREAD(Thread); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); @@ -1220,25 +1219,14 @@ KeSetBasePriorityThread(IN PKTHREAD Thread, { /* Reset the quantum and do the actual priority modification */ Thread->Quantum = Thread->QuantumReset; - KiSetPriorityThread(Thread, Priority, &Released); + KiSetPriorityThread(Thread, Priority); } /* Release thread lock */ KiReleaseThreadLock(Thread); - /* Check if lock was released */ - if (!Released) - { - /* Release the dispatcher database */ - KiReleaseDispatcherLock(OldIrql); - } - else - { - /* Lower IRQL only */ - KeLowerIrql(OldIrql); - } - - /* Return old increment */ + /* Release the dispatcher database and return old increment */ + KiReleaseDispatcherLock(OldIrql); return OldIncrement; } @@ -1276,7 +1264,6 @@ KeSetPriorityThread(IN PKTHREAD Thread, { KIRQL OldIrql; KPRIORITY OldPriority; - BOOLEAN Released = FALSE; ASSERT_THREAD(Thread); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); ASSERT((Priority <= HIGH_PRIORITY) && (Priority >= LOW_PRIORITY)); @@ -1302,23 +1289,14 @@ KeSetPriorityThread(IN PKTHREAD Thread, if ((Thread->BasePriority != 0) && !(Priority)) Priority = 1; /* Set the new Priority */ - KiSetPriorityThread(Thread, Priority, &Released); + KiSetPriorityThread(Thread, Priority); } /* Release thread lock */ KiReleaseThreadLock(Thread); - /* Check if lock was released */ - if (!Released) - { - /* Release the dispatcher database */ - KiReleaseDispatcherLock(OldIrql); - } - else - { - /* Lower IRQL only */ - KeLowerIrql(OldIrql); - } + /* Release the dispatcher database */ + KiReleaseDispatcherLock(OldIrql); /* Return Old Priority */ return OldPriority; diff --git a/reactos/ntoskrnl/ke/thrdschd.c b/reactos/ntoskrnl/ke/thrdschd.c index 7da63cbd423..57f43c1dc7a 100644 --- a/reactos/ntoskrnl/ke/thrdschd.c +++ b/reactos/ntoskrnl/ke/thrdschd.c @@ -14,8 +14,6 @@ /* GLOBALS *******************************************************************/ -LIST_ENTRY PriorityListHead[MAXIMUM_PRIORITY]; -ULONG PriorityListMask = 0; ULONG KiIdleSummary; ULONG KiIdleSMTSummary; @@ -30,7 +28,243 @@ KiQueueReadyThread(IN PKTHREAD Thread, KxQueueReadyThread(Thread, Prcb); } -static +VOID +NTAPI +KiDeferredReadyThread(IN PKTHREAD Thread) +{ + PKPRCB Prcb; + BOOLEAN Preempted; + ULONG Processor = 0; + KPRIORITY OldPriority; + PKTHREAD NextThread; + + /* Sanity checks */ + ASSERT(Thread->State == DeferredReady); + ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY)); + + /* Check if we have any adjusts to do */ + if (Thread->AdjustReason == AdjustBoost) + { + /* Lock the thread */ + KiAcquireThreadLock(Thread); + + /* Check if the priority is low enough to qualify for boosting */ + if ((Thread->Priority <= Thread->AdjustIncrement) && + (Thread->Priority < (LOW_REALTIME_PRIORITY - 3)) && + !(Thread->DisableBoost)) + { + /* Calculate the new priority based on the adjust increment */ + OldPriority = min(Thread->AdjustIncrement + 1, + LOW_REALTIME_PRIORITY - 1); + + /* Make sure we're not decreasing outside of the priority range */ + ASSERT((Thread->PriorityDecrement >= 0) && + (Thread->PriorityDecrement <= Thread->Priority)); + + /* Calculate the new priority decrement based on the boost */ + Thread->PriorityDecrement += ((SCHAR)OldPriority - Thread->Priority); + + /* Again verify that this decrement is valid */ + ASSERT((Thread->PriorityDecrement >= 0) && + (Thread->PriorityDecrement <= OldPriority)); + + /* Set the new priority */ + Thread->Priority = (SCHAR)OldPriority; + } + + /* We need 4 quanta, make sure we have them, then decrease by one */ + if (Thread->Quantum < 4) Thread->Quantum = 4; + Thread->Quantum--; + + /* Make sure the priority is still valid */ + ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY)); + + /* Release the lock and clear the adjust reason */ + KiReleaseThreadLock(Thread); + Thread->AdjustReason = AdjustNone; + } + else if (Thread->AdjustReason == AdjustUnwait) + { + /* Acquire the thread lock and check if this is a real-time thread */ + KiAcquireThreadLock(Thread); + if (Thread->Priority < LOW_REALTIME_PRIORITY) + { + /* It's not real time, but is it time critical? */ + if (Thread->BasePriority >= (LOW_REALTIME_PRIORITY - 2)) + { + /* It is, so simply reset its quantum */ + Thread->Quantum = Thread->QuantumReset; + } + else + { + /* Has the priority been adjusted previously? */ + if (!(Thread->PriorityDecrement) && (Thread->AdjustIncrement)) + { + /* Yes, reset its quantum */ + Thread->Quantum = Thread->QuantumReset; + } + + /* Wait code already handles quantum adjustment during APCs */ + if (Thread->WaitStatus != STATUS_KERNEL_APC) + { + /* Decrease the quantum by one and check if we're out */ + if (--Thread->Quantum <= 0) + { + /* We are, reset the quantum and get a new priority */ + Thread->Quantum = Thread->QuantumReset; + Thread->Priority = KiComputeNewPriority(Thread, 1); + } + } + } + + /* Now check if we have no decrement and boosts are enabled */ + if (!(Thread->PriorityDecrement) && !(Thread->DisableBoost)) + { + /* Make sure we have an increment */ + ASSERT(Thread->AdjustIncrement >= 0); + + /* Calculate the new priority after the increment */ + OldPriority = Thread->BasePriority + Thread->AdjustIncrement; + + /* Check if this new priority is higher */ + if (OldPriority > Thread->Priority) + { + /* Make sure we don't go into the real time range */ + if (OldPriority >= LOW_REALTIME_PRIORITY) + { + /* Normalize it back down one notch */ + OldPriority = LOW_REALTIME_PRIORITY - 1; + } + + /* Check if the priority is higher then the boosted base */ + if (OldPriority > (Thread->BasePriority + + Thread->AdjustIncrement)) + { + /* Setup a priority decrement to nullify the boost */ + Thread->PriorityDecrement = ((SCHAR)OldPriority - + Thread->BasePriority - + Thread->AdjustIncrement); + } + + /* Make sure that the priority decrement is valid */ + ASSERT((Thread->PriorityDecrement >= 0) && + (Thread->PriorityDecrement <= OldPriority)); + + /* Set this new priority */ + Thread->Priority = (SCHAR)OldPriority; + } + } + } + else + { + /* It's a real-time thread, so just reset its quantum */ + Thread->Quantum = Thread->QuantumReset; + } + + /* Make sure the priority makes sense */ + ASSERT((Thread->Priority >= 0) && (Thread->Priority <= HIGH_PRIORITY)); + + /* Release the thread lock and reset the adjust reason */ + KiReleaseThreadLock(Thread); + Thread->AdjustReason = AdjustNone; + } + + /* Clear thread preemption status and save current values */ + Preempted = Thread->Preempted; + OldPriority = Thread->Priority; + Thread->Preempted = FALSE; + + /* Queue the thread on CPU 0 and get the PRCB */ + Thread->NextProcessor = 0; + Prcb = KiProcessorBlock[0]; + + /* Check if we have an idle summary */ + if (KiIdleSummary) + { + /* Clear it and set this thread as the next one */ + KiIdleSummary = 0; + Thread->State = Standby; + Prcb->NextThread = Thread; + return; + } + + /* Set the CPU number */ + Thread->NextProcessor = (UCHAR)Processor; + + /* Get the next scheduled thread */ + NextThread = Prcb->NextThread; + if (NextThread) + { + /* Sanity check */ + ASSERT(NextThread->State == Standby); + + /* Check if priority changed */ + if (OldPriority > NextThread->Priority) + { + /* Preempt the thread */ + NextThread->Preempted = TRUE; + + /* Put this one as the next one */ + Thread->State = Standby; + Prcb->NextThread = Thread; + + /* Set it in deferred ready mode */ + NextThread->State = DeferredReady; + NextThread->DeferredProcessor = Prcb->Number; + KiReleasePrcbLock(Prcb); + KiDeferredReadyThread(NextThread); + return; + } + } + else + { + /* Set the next thread as the current thread */ + NextThread = Prcb->CurrentThread; + if (OldPriority > NextThread->Priority) + { + /* Preempt it if it's already running */ + if (NextThread->State == Running) NextThread->Preempted = TRUE; + + /* Set the thread on standby and as the next thread */ + Thread->State = Standby; + Prcb->NextThread = Thread; + + /* Release the lock */ + KiReleasePrcbLock(Prcb); + + /* Check if we're running on another CPU */ + if (KeGetCurrentProcessorNumber() != Thread->NextProcessor) + { + /* We are, send an IPI */ + KiIpiSendRequest(AFFINITY_MASK(Thread->NextProcessor), IPI_DPC); + } + return; + } + } + + /* Sanity check */ + ASSERT((OldPriority >= 0) && (OldPriority <= HIGH_PRIORITY)); + + /* Set this thread as ready */ + Thread->State = Ready; + Thread->WaitTime = KeTickCount.LowPart; + + /* Insert this thread in the appropriate order */ + Preempted ? InsertHeadList(&Prcb->DispatcherReadyListHead[OldPriority], + &Thread->WaitListEntry) : + InsertTailList(&Prcb->DispatcherReadyListHead[OldPriority], + &Thread->WaitListEntry); + + /* Update the ready summary */ + Prcb->ReadySummary |= PRIORITY_MASK(OldPriority); + + /* Sanity check */ + ASSERT(OldPriority == Thread->Priority); + + /* Release the lock */ + KiReleasePrcbLock(Prcb); +} + VOID KiInsertIntoThreadList(KPRIORITY Priority, PKTHREAD Thread) @@ -44,23 +278,21 @@ KiInsertIntoThreadList(KPRIORITY Priority, KEBUGCHECK(0); } - InsertTailList(&PriorityListHead[Priority], &Thread->WaitListEntry); - PriorityListMask |= (1 << Priority); + InsertTailList(&KeGetCurrentPrcb()->DispatcherReadyListHead[Priority], &Thread->WaitListEntry); + KeGetCurrentPrcb()->ReadySummary |= (1 << Priority); } -static VOID KiRemoveFromThreadList(PKTHREAD Thread) { ASSERT(Ready == Thread->State); RemoveEntryList(&Thread->WaitListEntry); - if (IsListEmpty(&PriorityListHead[(ULONG)Thread->Priority])) { + if (IsListEmpty(&KeGetCurrentPrcb()->DispatcherReadyListHead[Thread->Priority])) { - PriorityListMask &= ~(1 << Thread->Priority); + KeGetCurrentPrcb()->ReadySummary &= ~(1 << Thread->Priority); } } -static PKTHREAD KiScanThreadList(KPRIORITY Priority, KAFFINITY Affinity) @@ -70,9 +302,9 @@ KiScanThreadList(KPRIORITY Priority, Mask = (1 << Priority); - if (PriorityListMask & Mask) { + if (KeGetCurrentPrcb()->ReadySummary & Mask) { - LIST_FOR_EACH(current, &PriorityListHead[Priority], KTHREAD, WaitListEntry) { + LIST_FOR_EACH(current, &KeGetCurrentPrcb()->DispatcherReadyListHead[Priority], KTHREAD, WaitListEntry) { if (current->State != Ready) { @@ -165,11 +397,18 @@ KiDispatchThreadNoLock(ULONG NewThreadStatus) } VOID -NTAPI -KiDeferredReadyThread(IN PKTHREAD Thread) +STDCALL +KiDispatchThread(ULONG NewThreadStatus) { - /* FIXME: Not yet implemented */ - KEBUGCHECK(0); + KIRQL OldIrql; + + if (KeGetCurrentPrcb()->IdleThread == NULL) { + return; + } + + OldIrql = KiAcquireDispatcherLock(); + KiDispatchThreadNoLock(NewThreadStatus); + KeLowerIrql(OldIrql); } PKTHREAD @@ -203,15 +442,71 @@ FASTCALL KiSwapThread(IN PKTHREAD CurrentThread, IN PKPRCB Prcb) { - BOOLEAN ApcState; + BOOLEAN ApcState = FALSE; + KIRQL WaitIrql; + LONG_PTR WaitStatus; + PKTHREAD NextThread; +#ifdef NEW_SCHEDULER + PEPROCESS HackOfDoom = PsGetCurrentProcess(); +#endif ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL); -#ifdef NEW_SCHEDULER + /* Acquire the PRCB lock */ + KiAcquirePrcbLock(Prcb); + /* Get the next thread */ + NextThread = Prcb->NextThread; + if (NextThread) + { + /* Already got a thread, set it up */ + Prcb->NextThread = NULL; + Prcb->CurrentThread = NextThread; + NextThread->State = Running; + } + else + { +#ifdef NEW_SCHEDULER + /* Try to find a ready thread */ + NextThread = KiSelectReadyThread(0, Prcb); + if (NextThread) + { + /* Switch to it */ + Prcb->CurrentThread = NextThread; + NextThread->State = Running; + } + else + { + /* Set the idle summary */ + InterlockedOr(&KiIdleSummary, Prcb->SetMember); + + /* Schedule the idle thread */ + NextThread = Prcb->IdleThread; + Prcb->CurrentThread = NextThread; + NextThread->State = Running; + } #else - /* Find a new thread to run */ - ApcState = KiDispatchThreadNoLock(Waiting); + /* Find a new thread to run */ + ApcState = KiDispatchThreadNoLock(Waiting); #endif + } + + /* Sanity check and release the PRCB */ + ASSERT(CurrentThread != Prcb->IdleThread); + KiReleasePrcbLock(Prcb); + + /* Save the wait IRQL */ + WaitIrql = CurrentThread->WaitIrql; + +#ifdef NEW_SCHEDULER + /* REACTOS Mm Hack of Doom */ + MmUpdatePageDir(HackOfDoom,((PETHREAD)NextThread)->ThreadsProcess, sizeof(EPROCESS)); + + /* Swap contexts */ + ApcState = KiSwapContext(CurrentThread, NextThread); +#endif + + /* Get the wait status */ + WaitStatus = CurrentThread->WaitStatus; /* Check if we need to deliver APCs */ if (ApcState) @@ -221,29 +516,12 @@ KiSwapThread(IN PKTHREAD CurrentThread, /* Deliver APCs */ KiDeliverApc(KernelMode, NULL, NULL); - ASSERT(CurrentThread->WaitIrql == 0); + ASSERT(WaitIrql == 0); } - /* Lower IRQL back to what it was */ - KfLowerIrql(CurrentThread->WaitIrql); - - /* Return the wait status */ - return CurrentThread->WaitStatus; -} - -VOID -STDCALL -KiDispatchThread(ULONG NewThreadStatus) -{ - KIRQL OldIrql; - - if (KeGetCurrentPrcb()->IdleThread == NULL) { - return; - } - - OldIrql = KiAcquireDispatcherLock(); - KiDispatchThreadNoLock(NewThreadStatus); - KeLowerIrql(OldIrql); + /* Lower IRQL back to what it was and return the wait status */ + KeLowerIrql(WaitIrql); + return WaitStatus; } VOID @@ -289,6 +567,7 @@ NTAPI KiAdjustQuantumThread(IN PKTHREAD Thread) { PKPRCB Prcb = KeGetCurrentPrcb(); + PKTHREAD NextThread; /* Acquire thread and PRCB lock */ KiAcquireThreadLock(Thread); @@ -327,6 +606,7 @@ KiAdjustQuantumThread(IN PKTHREAD Thread) } #else /* We need to dispatch a new thread */ + NextThread = NULL; KiDispatchThread(Ready); #endif } @@ -339,10 +619,9 @@ KiAdjustQuantumThread(IN PKTHREAD Thread) } VOID -NTAPI +FASTCALL KiSetPriorityThread(IN PKTHREAD Thread, - IN KPRIORITY Priority, - OUT PBOOLEAN Released) + IN KPRIORITY Priority) { PKPRCB Prcb; ULONG Processor; @@ -381,7 +660,8 @@ KiSetPriorityThread(IN PKTHREAD Thread, if (RemoveEntryList(&Thread->WaitListEntry)) { /* Update the ready summary */ - Prcb->ReadySummary ^= PRIORITY_MASK(Thread->Priority); + Prcb->ReadySummary ^= PRIORITY_MASK(Thread-> + Priority); } #else KiRemoveFromThreadList(Thread); @@ -393,8 +673,7 @@ KiSetPriorityThread(IN PKTHREAD Thread, /* Re-insert it at its current priority */ #ifndef NEW_SCHEDULER KiInsertIntoThreadList(Priority, Thread); - KiDispatchThreadNoLock(Ready); - *Released = TRUE; + //KiDispatchThreadNoLock(Ready); #else KiInsertDeferredReadyList(Thread); #endif @@ -486,14 +765,13 @@ KiSetPriorityThread(IN PKTHREAD Thread, } #else /* Check for threads with a higher priority */ - if (PriorityListMask & ~((1 << (Priority + 1)) - 1)) + if (KeGetCurrentPrcb()->ReadySummary & ~((1 << (Priority + 1)) - 1)) { /* Found a thread, is it us? */ if (Thread == KeGetCurrentThread()) { /* Dispatch us */ - KiDispatchThreadNoLock(Ready); - *Released = TRUE; + //KiDispatchThreadNoLock(Ready); return; } } @@ -535,9 +813,6 @@ KiSetPriorityThread(IN PKTHREAD Thread, break; } } - - /* Return to caller */ - *Released = FALSE; } KAFFINITY @@ -579,13 +854,75 @@ NTSTATUS NTAPI NtYieldExecution(VOID) { - // - // TODO (nothing too hard, just want to test out other code) - // - //DPRINT1("NO YIELD PERFORMED! If you see this, contact Alex\n"); - //return STATUS_NO_YIELD_PERFORMED; +#ifdef NEW_SCHEDULER + NTSTATUS Status = STATUS_NO_YIELD_PERFORMED; + KIRQL OldIrql; + PKPRCB Prcb = KeGetCurrentPrcb(); + PKTHREAD Thread = KeGetCurrentThread(), NextThread; + + /* Fail if there's no ready summary */ + if (!Prcb->ReadySummary) return Status; + + /* Raise IRQL to synch */ + OldIrql = KeRaiseIrqlToSynchLevel(); + + /* Now check if there's still a ready summary */ + if (Prcb->ReadySummary) + { + /* Acquire thread and PRCB lock */ + KiAcquireThreadLock(Thread); + KiAcquirePrcbLock(Prcb); + + /* Find a new thread to run if none was selected */ + if (!Prcb->NextThread) Prcb->NextThread = KiSelectReadyThread(1, Prcb); + + /* Make sure we still have a next thread to schedule */ + NextThread = Prcb->NextThread; + if (NextThread) + { + /* Reset quantum and recalculate priority */ + Thread->Quantum = Thread->QuantumReset; + Thread->Priority = KiComputeNewPriority(Thread, 1); + + /* Release the thread lock */ + KiReleaseThreadLock(Thread); + + /* Set context swap busy */ + KiSetThreadSwapBusy(Thread); + + /* Set the new thread as running */ + Prcb->NextThread = NULL; + Prcb->CurrentThread = NextThread; + NextThread->State = Running; + + /* Setup a yield wait and queue the thread */ + Thread->WaitReason = WrYieldExecution; + KxQueueReadyThread(Thread, Prcb); + + /* Make it wait at APC_LEVEL */ + Thread->WaitIrql = APC_LEVEL; + + /* Sanity check */ + ASSERT(OldIrql <= DISPATCH_LEVEL); + + /* Swap to new thread */ + KiSwapContext(Thread, NextThread); + Status = STATUS_SUCCESS; + } + else + { + /* Release the PRCB and thread lock */ + KiReleasePrcbLock(Prcb); + KiReleaseThreadLock(Thread); + } + } + + /* Lower IRQL and return */ + KeLowerIrql(OldIrql); + return Status; +#else KiDispatchThread(Ready); return STATUS_SUCCESS; +#endif } - diff --git a/reactos/ntoskrnl/ps/psmgr.c b/reactos/ntoskrnl/ps/psmgr.c index 41a94f680a4..7ed35892743 100644 --- a/reactos/ntoskrnl/ps/psmgr.c +++ b/reactos/ntoskrnl/ps/psmgr.c @@ -289,7 +289,6 @@ PspInitPhase0(VOID) PETHREAD SysThread; MM_SYSTEMSIZE SystemSize; UNICODE_STRING Name; - ULONG i; OBJECT_TYPE_INITIALIZER ObjectTypeInitializer; /* FIXME: Initialize Lock Data do it STATIC */ @@ -380,12 +379,6 @@ PspInitPhase0(VOID) ObjectTypeInitializer.DeleteProcedure = PspDeleteProcess; ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &PsProcessType); - /* Setup ROS Scheduler lists (HACK!) */ - for (i = 0; i < MAXIMUM_PRIORITY; i++) - { - InitializeListHead(&PriorityListHead[i]); - } - /* Initialize the Thread type */ RtlInitUnicodeString(&Name, L"Thread"); ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);