Author: ion Date: Tue Jan 16 23:49:40 2007 New Revision: 25490
URL: http://svn.reactos.org/svn/reactos?rev=25490&view=rev Log: [22 bug fixes]: - Make KiComputeNewPriority accept various priority adjuments instead of always assuming an increase of 1 priority level. - Fix ASSERT in KeSetEventBoostPriority: API is valid *only* for Synchronization events, not notification ones. - Use proper KiComputeNewPriority call in KeSetEventBoostPriority, since we're not adjusting by 1. - Make sure the FreezeCount is also 0 in KeAlertResumeThread, before signalling the suspend semaphore. - Simply alert-mode check in KeAlertThread. - Don't exit the critical region in KeFreezeAllThreads, it needs to be held. - Don't enter a critical region in KeThawAllThreads, it should already have been entered; release it after thawing is complete. - Also change the list loop in these functions to always start with the first thread. - Copy over boost-disable flag in KeStartThread. - Don't acquire the dispatcher lock in KeTestAlertThread. - Set the KernelStackResident flag to TRUE in KeInitThread. - Fix KeSetIdealProcessorThread to check the CPU is valid on the system, not valid across all valid CPU numbers. Also fix it to compare affinity, not processor. - Fix KeSetBasePriorityThread to properly call KiComputeNewPriority with an adjustment of 0, and then properly manually adjust with the delta between the new base priority and the old base priority. - Also normalize the new priority if it's too low. - Always set the priority decrement back to 0 when KeSetPriorityThread is called. - Normalize the priority in KeSetPriorityThread if it falls too low. - Fix process stack count check in KeTerminateThread. - Acquire thread and PRCB lock in KiAdjustQuantumThread. - Use KiComputeNewPriority in KiAdjustQuantumThread. - Dispatch a new thread in KiAdjustQuantumThread to take into account the new scheduler settings. - Thread priorities should make more sense now...
Modified: trunk/reactos/ntoskrnl/include/internal/ke_x.h trunk/reactos/ntoskrnl/ke/dpc.c trunk/reactos/ntoskrnl/ke/event.c trunk/reactos/ntoskrnl/ke/thrdobj.c trunk/reactos/ntoskrnl/ke/thrdschd.c
Modified: trunk/reactos/ntoskrnl/include/internal/ke_x.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/k... ============================================================================== --- trunk/reactos/ntoskrnl/include/internal/ke_x.h (original) +++ trunk/reactos/ntoskrnl/include/internal/ke_x.h Tue Jan 16 23:49:40 2007 @@ -1304,7 +1304,8 @@ // SCHAR FORCEINLINE -KiComputeNewPriority(IN PKTHREAD Thread) +KiComputeNewPriority(IN PKTHREAD Thread, + IN SCHAR Adjustment) { SCHAR Priority;
@@ -1319,7 +1320,7 @@ if (Priority < LOW_REALTIME_PRIORITY) { /* Decrease priority by the priority decrement */ - Priority -= (Thread->PriorityDecrement + 1); + Priority -= (Thread->PriorityDecrement + Adjustment);
/* Don't go out of bounds */ if (Priority < Thread->BasePriority) Priority = Thread->BasePriority;
Modified: trunk/reactos/ntoskrnl/ke/dpc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/dpc.c?rev=25490... ============================================================================== --- trunk/reactos/ntoskrnl/ke/dpc.c (original) +++ trunk/reactos/ntoskrnl/ke/dpc.c Tue Jan 16 23:49:40 2007 @@ -39,7 +39,6 @@ NTAPI KiQuantumEnd(VOID) { - KPRIORITY Priority; PKPRCB Prcb = KeGetCurrentPrcb(); PKTHREAD NextThread, Thread = Prcb->CurrentThread;
@@ -66,7 +65,7 @@ Thread->Quantum = Thread->QuantumReset;
/* Calculate new priority */ - Priority = Thread->Priority = KiComputeNewPriority(Thread); + Thread->Priority = KiComputeNewPriority(Thread, 1);
/* Check if a new thread is scheduled */ if (!Prcb->NextThread) @@ -337,7 +336,7 @@ if (&Prcb->DpcData[DPC_THREADED].DpcListHead == &DpcData->DpcListHead) { /* Make sure a threaded DPC isn't already active */ - if (!(Prcb->DpcThreadActive) && (!Prcb->DpcThreadRequested)) + if (!(Prcb->DpcThreadActive) && !(Prcb->DpcThreadRequested)) { /* FIXME: Setup Threaded DPC */ ASSERT(FALSE); @@ -346,7 +345,7 @@ else { /* Make sure a DPC isn't executing already */ - if ((!Prcb->DpcRoutineActive) && (!Prcb->DpcInterruptRequested)) + if (!(Prcb->DpcRoutineActive) && !(Prcb->DpcInterruptRequested)) { /* Check if this is the same CPU */ if (Prcb != CurrentPrcb)
Modified: trunk/reactos/ntoskrnl/ke/event.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/event.c?rev=254... ============================================================================== --- trunk/reactos/ntoskrnl/ke/event.c (original) +++ trunk/reactos/ntoskrnl/ke/event.c Tue Jan 16 23:49:40 2007 @@ -237,7 +237,7 @@ KIRQL OldIrql; PKWAIT_BLOCK WaitBlock; PKTHREAD Thread = KeGetCurrentThread(), WaitThread; - ASSERT_EVENT(Event); + ASSERT(Event->Header.Type == SynchronizationEvent); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Acquire Dispatcher Database Lock */ @@ -275,14 +275,14 @@ if (WaitingThread) *WaitingThread = WaitThread;
/* Calculate new priority */ - Thread->Priority = KiComputeNewPriority(Thread); + Thread->Priority = KiComputeNewPriority(Thread, 0);
/* Unlink the waiting thread */ - KiUnlinkThread(WaitThread, STATUS_WAIT_0); + KiUnlinkThread(WaitThread, STATUS_SUCCESS);
/* Request priority boosting */ WaitThread->AdjustIncrement = Thread->Priority; - WaitThread->AdjustReason = 2; + WaitThread->AdjustReason = AdjustBoost;
/* Ready the thread */ KiReadyThread(WaitThread);
Modified: trunk/reactos/ntoskrnl/ke/thrdobj.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/thrdobj.c?rev=2... ============================================================================== --- trunk/reactos/ntoskrnl/ke/thrdobj.c (original) +++ trunk/reactos/ntoskrnl/ke/thrdobj.c Tue Jan 16 23:49:40 2007 @@ -134,7 +134,8 @@ if (PreviousCount) { /* Decrease count. If we are now zero, unwait it completely */ - if (--Thread->SuspendCount) + Thread->SuspendCount--; + if (!(Thread->SuspendCount) && !(Thread->FreezeCount)) { /* Signal and satisfy */ Thread->SuspendSemaphore.Header.SignalState++; @@ -171,8 +172,8 @@ { /* Check if the thread is alertable, and blocked in the given mode */ if ((Thread->State == Waiting) && - ((AlertMode == KernelMode) || (Thread->WaitMode == AlertMode)) && - (Thread->Alertable)) + (Thread->Alertable) && + (AlertMode <= Thread->WaitMode)) { /* Abort the wait to alert the thread */ KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT); @@ -260,7 +261,7 @@ /* Loop the Process's Threads */ ListHead = &Process->ThreadListHead; NextEntry = ListHead->Flink; - while (NextEntry != ListHead) + do { /* Get the current thread */ Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry); @@ -307,14 +308,11 @@
/* Move to the next thread */ NextEntry = NextEntry->Flink; - } + } while (NextEntry != ListHead);
/* Release the process lock and exit the dispatcher */ KiReleaseProcessLock(&LockHandle); KiExitDispatcher(LockHandle.OldIrql); - - /* Leave the critical region */ - KeLeaveCriticalRegion(); }
ULONG @@ -367,6 +365,7 @@ PKTHREAD Thread = KeGetCurrentThread(); PLIST_ENTRY NextEntry, ListHead; PKMUTANT Mutant; + ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Optimized path if nothing is on the list at the moment */ if (IsListEmpty(&Thread->MutantListHead)) return; @@ -430,6 +429,7 @@ PKPROCESS Process = Thread->ApcState.Process;
/* Setup static fields from parent */ + Thread->DisableBoost = Process->DisableBoost; Thread->Iopl = Process->Iopl; Thread->Quantum = Process->QuantumReset; Thread->QuantumReset = Process->QuantumReset; @@ -593,13 +593,10 @@ /* Lock the process */ KiAcquireProcessLock(Process, &LockHandle);
- /* Enter a critical region */ - KeEnterCriticalRegion(); - /* Loop the Process's Threads */ ListHead = &Process->ThreadListHead; NextEntry = ListHead->Flink; - while (NextEntry != ListHead) + do { /* Get the current thread */ Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry); @@ -634,7 +631,7 @@
/* Go to the next one */ NextEntry = NextEntry->Flink; - } + } while (NextEntry != ListHead);
/* Release the process lock and exit the dispatcher */ KiReleaseProcessLock(&LockHandle); @@ -656,7 +653,6 @@
/* Lock the Dispatcher Database and the APC Queue */ KiAcquireApcLock(Thread, &ApcLock); - KiAcquireDispatcherLockAtDpcLevel();
/* Save the old State */ OldState = Thread->Alerted[AlertMode]; @@ -675,9 +671,7 @@ }
/* Release Locks and return the Old State */ - KiReleaseDispatcherLockFromDpcLevel(); - KiReleaseApcLockFromDpcLevel(&ApcLock); - KiExitDispatcher(ApcLock.OldIrql); + KiReleaseApcLock(&ApcLock); return OldState; }
@@ -718,7 +712,8 @@ Thread->EnableStackSwap = FALSE;//TRUE; Thread->IdealProcessor = 1; Thread->SwapBusy = FALSE; - Thread->AdjustReason = 0; + Thread->KernelStackResident = TRUE; + Thread->AdjustReason = AdjustNone;
/* Initialize the lock */ KeInitializeSpinLock(&Thread->ThreadLock); @@ -1020,10 +1015,10 @@ OldIdealProcessor = Thread->UserIdealProcessor;
/* Make sure a valid CPU was given */ - if (Processor < MAXIMUM_PROCESSORS) + if (Processor < KeNumberProcessors) { /* Check if the user ideal CPU is in the affinity */ - if (Thread->UserIdealProcessor & AFFINITY_MASK(Processor)) + if (Thread->Affinity & AFFINITY_MASK(Processor)) { /* Set the ideal processor */ Thread->IdealProcessor = Processor; @@ -1197,7 +1192,8 @@ else { /* Otherwise, calculate the new priority */ - Priority = KiComputeNewPriority(Thread); + Priority = KiComputeNewPriority(Thread, 0); + Priority += (BasePriority - OldBasePriority);
/* Check if it entered the real-time range */ if (Priority >= LOW_REALTIME_PRIORITY) @@ -1205,6 +1201,11 @@ /* Normalize it down to the highest dynamic priority */ Priority = LOW_REALTIME_PRIORITY - 1; } + else if (Priority <= LOW_PRIORITY) + { + /* It went too low, normalize it */ + Priority = 1; + } } }
@@ -1291,6 +1292,7 @@ ASSERT_THREAD(Thread); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); ASSERT((Priority <= HIGH_PRIORITY) && (Priority >= LOW_PRIORITY)); + ASSERT(KeIsExecutingDpc() == FALSE);
/* Lock the Dispatcher Database */ OldIrql = KiAcquireDispatcherLock(); @@ -1298,15 +1300,18 @@ /* Lock the thread */ KiAcquireThreadLock(Thread);
- /* Save the old Priority */ + /* Save the old Priority and reset decrement */ OldPriority = Thread->Priority; + Thread->PriorityDecrement = 0;
/* Make sure that an actual change is being done */ - if (OldPriority != Priority) - { - /* Reset the Quantum and Decrements */ + if (Priority != Thread->Priority) + { + /* Reset the quantum */ Thread->Quantum = Thread->QuantumReset; - Thread->PriorityDecrement = 0; + + /* Check if priority is being set too low and normalize if so */ + if ((Thread->BasePriority != 0) && !(Priority)) Priority = 1;
/* Set the new Priority */ KiSetPriorityThread(Thread, Priority, &Released); @@ -1417,7 +1422,7 @@ ASSERT(Process->StackCount != 0); ASSERT(Process->State == ProcessInMemory); Process->StackCount--; - if (!Process->StackCount) + if (!(Process->StackCount) && !(IsListEmpty(&Process->ThreadListHead))) { /* FIXME: Swap stacks */ }
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 Tue Jan 16 23:49:40 2007 @@ -252,11 +252,15 @@ STDCALL KiAdjustQuantumThread(IN PKTHREAD Thread) { - KPRIORITY Priority; + PKPRCB Prcb = KeGetCurrentPrcb(); + + /* Acquire thread and PRCB lock */ + KiAcquireThreadLock(Thread); + KiAcquirePrcbLock(Prcb);
/* Don't adjust for RT threads */ if ((Thread->Priority < LOW_REALTIME_PRIORITY) && - Thread->BasePriority < LOW_REALTIME_PRIORITY - 2) + (Thread->BasePriority < (LOW_REALTIME_PRIORITY - 2))) { /* Decrease Quantum by one and see if we've ran out */ if (--Thread->Quantum <= 0) @@ -265,46 +269,45 @@ Thread->Quantum = Thread->QuantumReset;
/* Calculate new Priority */ - Priority = Thread->Priority - (Thread->PriorityDecrement + 1); - - /* Normalize it if we've gone too low */ - if (Priority < Thread->BasePriority) Priority = Thread->BasePriority; - - /* Reset the priority decrement, we've done it */ - Thread->PriorityDecrement = 0; - - /* Set the new priority, if needed */ - if (Priority != Thread->Priority) + Thread->Priority = KiComputeNewPriority(Thread, 1); + +#ifdef NEW_SCHEDULER + /* Check if there's no next thread scheduled */ + if (!Prcb->NextThread) { - /* - * FIXME: This should be a call to KiSetPriorityThread but - * due to the current ""scheduler"" in ROS, it can't be done - * cleanly since it actualyl dispatches threads instead. - */ - Thread->Priority = (SCHAR)Priority; + /* Select a new thread and set it on standby */ + NextThread = KiSelectNextThread(Prcb); + NextThread->State = Standby; + Prcb->NextThread = NextThread; } else { - /* FIXME: Priority hasn't changed, find a new thread */ - } - } - } - - /* Nothing to do... */ - return; + /* This thread can be preempted again */ + Thread->Preempted = FALSE; + } +#else + /* We need to dispatch a new thread */ + KiDispatchThread(Ready); +#endif + } + } + + /* Release locks */ + KiReleasePrcbLock(Prcb); + KiReleaseThreadLock(Thread); }
VOID STDCALL -KiSetPriorityThread(PKTHREAD Thread, - KPRIORITY Priority, - PBOOLEAN Released) +KiSetPriorityThread(IN PKTHREAD Thread, + IN KPRIORITY Priority, + OUT PBOOLEAN Released) { KPRIORITY OldPriority = Thread->Priority; ULONG Mask; - int i; + ULONG i; PKPCR Pcr; - DPRINT("Changing prio to : %lx\n", Priority); + ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));
/* Check if priority changed */ if (OldPriority != Priority) @@ -459,3 +462,4 @@ return STATUS_SUCCESS; }
+