[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...

svn path=/trunk/; revision=25490
This commit is contained in:
Alex Ionescu 2007-01-16 20:49:40 +00:00
parent dde6333e88
commit c15d054bad
5 changed files with 70 additions and 61 deletions

View file

@ -1304,7 +1304,8 @@ KiSelectReadyThread(IN KPRIORITY Priority,
// //
SCHAR SCHAR
FORCEINLINE FORCEINLINE
KiComputeNewPriority(IN PKTHREAD Thread) KiComputeNewPriority(IN PKTHREAD Thread,
IN SCHAR Adjustment)
{ {
SCHAR Priority; SCHAR Priority;
@ -1319,7 +1320,7 @@ KiComputeNewPriority(IN PKTHREAD Thread)
if (Priority < LOW_REALTIME_PRIORITY) if (Priority < LOW_REALTIME_PRIORITY)
{ {
/* Decrease priority by the priority decrement */ /* Decrease priority by the priority decrement */
Priority -= (Thread->PriorityDecrement + 1); Priority -= (Thread->PriorityDecrement + Adjustment);
/* Don't go out of bounds */ /* Don't go out of bounds */
if (Priority < Thread->BasePriority) Priority = Thread->BasePriority; if (Priority < Thread->BasePriority) Priority = Thread->BasePriority;

View file

@ -39,7 +39,6 @@ VOID
NTAPI NTAPI
KiQuantumEnd(VOID) KiQuantumEnd(VOID)
{ {
KPRIORITY Priority;
PKPRCB Prcb = KeGetCurrentPrcb(); PKPRCB Prcb = KeGetCurrentPrcb();
PKTHREAD NextThread, Thread = Prcb->CurrentThread; PKTHREAD NextThread, Thread = Prcb->CurrentThread;
@ -66,7 +65,7 @@ KiQuantumEnd(VOID)
Thread->Quantum = Thread->QuantumReset; Thread->Quantum = Thread->QuantumReset;
/* Calculate new priority */ /* Calculate new priority */
Priority = Thread->Priority = KiComputeNewPriority(Thread); Thread->Priority = KiComputeNewPriority(Thread, 1);
/* Check if a new thread is scheduled */ /* Check if a new thread is scheduled */
if (!Prcb->NextThread) if (!Prcb->NextThread)
@ -337,7 +336,7 @@ KeInsertQueueDpc(IN PKDPC Dpc,
if (&Prcb->DpcData[DPC_THREADED].DpcListHead == &DpcData->DpcListHead) if (&Prcb->DpcData[DPC_THREADED].DpcListHead == &DpcData->DpcListHead)
{ {
/* Make sure a threaded DPC isn't already active */ /* Make sure a threaded DPC isn't already active */
if (!(Prcb->DpcThreadActive) && (!Prcb->DpcThreadRequested)) if (!(Prcb->DpcThreadActive) && !(Prcb->DpcThreadRequested))
{ {
/* FIXME: Setup Threaded DPC */ /* FIXME: Setup Threaded DPC */
ASSERT(FALSE); ASSERT(FALSE);
@ -346,7 +345,7 @@ KeInsertQueueDpc(IN PKDPC Dpc,
else else
{ {
/* Make sure a DPC isn't executing already */ /* 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 */ /* Check if this is the same CPU */
if (Prcb != CurrentPrcb) if (Prcb != CurrentPrcb)

View file

@ -237,7 +237,7 @@ KeSetEventBoostPriority(IN PKEVENT Event,
KIRQL OldIrql; KIRQL OldIrql;
PKWAIT_BLOCK WaitBlock; PKWAIT_BLOCK WaitBlock;
PKTHREAD Thread = KeGetCurrentThread(), WaitThread; PKTHREAD Thread = KeGetCurrentThread(), WaitThread;
ASSERT_EVENT(Event); ASSERT(Event->Header.Type == SynchronizationEvent);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Acquire Dispatcher Database Lock */ /* Acquire Dispatcher Database Lock */
@ -275,14 +275,14 @@ KeSetEventBoostPriority(IN PKEVENT Event,
if (WaitingThread) *WaitingThread = WaitThread; if (WaitingThread) *WaitingThread = WaitThread;
/* Calculate new priority */ /* Calculate new priority */
Thread->Priority = KiComputeNewPriority(Thread); Thread->Priority = KiComputeNewPriority(Thread, 0);
/* Unlink the waiting thread */ /* Unlink the waiting thread */
KiUnlinkThread(WaitThread, STATUS_WAIT_0); KiUnlinkThread(WaitThread, STATUS_SUCCESS);
/* Request priority boosting */ /* Request priority boosting */
WaitThread->AdjustIncrement = Thread->Priority; WaitThread->AdjustIncrement = Thread->Priority;
WaitThread->AdjustReason = 2; WaitThread->AdjustReason = AdjustBoost;
/* Ready the thread */ /* Ready the thread */
KiReadyThread(WaitThread); KiReadyThread(WaitThread);

View file

@ -134,7 +134,8 @@ KeAlertResumeThread(IN PKTHREAD Thread)
if (PreviousCount) if (PreviousCount)
{ {
/* Decrease count. If we are now zero, unwait it completely */ /* Decrease count. If we are now zero, unwait it completely */
if (--Thread->SuspendCount) Thread->SuspendCount--;
if (!(Thread->SuspendCount) && !(Thread->FreezeCount))
{ {
/* Signal and satisfy */ /* Signal and satisfy */
Thread->SuspendSemaphore.Header.SignalState++; Thread->SuspendSemaphore.Header.SignalState++;
@ -171,8 +172,8 @@ KeAlertThread(IN PKTHREAD Thread,
{ {
/* Check if the thread is alertable, and blocked in the given mode */ /* Check if the thread is alertable, and blocked in the given mode */
if ((Thread->State == Waiting) && if ((Thread->State == Waiting) &&
((AlertMode == KernelMode) || (Thread->WaitMode == AlertMode)) && (Thread->Alertable) &&
(Thread->Alertable)) (AlertMode <= Thread->WaitMode))
{ {
/* Abort the wait to alert the thread */ /* Abort the wait to alert the thread */
KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT); KiUnwaitThread(Thread, STATUS_ALERTED, THREAD_ALERT_INCREMENT);
@ -260,7 +261,7 @@ KeFreezeAllThreads(VOID)
/* Loop the Process's Threads */ /* Loop the Process's Threads */
ListHead = &Process->ThreadListHead; ListHead = &Process->ThreadListHead;
NextEntry = ListHead->Flink; NextEntry = ListHead->Flink;
while (NextEntry != ListHead) do
{ {
/* Get the current thread */ /* Get the current thread */
Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry); Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
@ -307,14 +308,11 @@ KeFreezeAllThreads(VOID)
/* Move to the next thread */ /* Move to the next thread */
NextEntry = NextEntry->Flink; NextEntry = NextEntry->Flink;
} } while (NextEntry != ListHead);
/* Release the process lock and exit the dispatcher */ /* Release the process lock and exit the dispatcher */
KiReleaseProcessLock(&LockHandle); KiReleaseProcessLock(&LockHandle);
KiExitDispatcher(LockHandle.OldIrql); KiExitDispatcher(LockHandle.OldIrql);
/* Leave the critical region */
KeLeaveCriticalRegion();
} }
ULONG ULONG
@ -367,6 +365,7 @@ KeRundownThread(VOID)
PKTHREAD Thread = KeGetCurrentThread(); PKTHREAD Thread = KeGetCurrentThread();
PLIST_ENTRY NextEntry, ListHead; PLIST_ENTRY NextEntry, ListHead;
PKMUTANT Mutant; PKMUTANT Mutant;
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
/* Optimized path if nothing is on the list at the moment */ /* Optimized path if nothing is on the list at the moment */
if (IsListEmpty(&Thread->MutantListHead)) return; if (IsListEmpty(&Thread->MutantListHead)) return;
@ -430,6 +429,7 @@ KeStartThread(IN OUT PKTHREAD Thread)
PKPROCESS Process = Thread->ApcState.Process; PKPROCESS Process = Thread->ApcState.Process;
/* Setup static fields from parent */ /* Setup static fields from parent */
Thread->DisableBoost = Process->DisableBoost;
Thread->Iopl = Process->Iopl; Thread->Iopl = Process->Iopl;
Thread->Quantum = Process->QuantumReset; Thread->Quantum = Process->QuantumReset;
Thread->QuantumReset = Process->QuantumReset; Thread->QuantumReset = Process->QuantumReset;
@ -593,13 +593,10 @@ KeThawAllThreads(VOID)
/* Lock the process */ /* Lock the process */
KiAcquireProcessLock(Process, &LockHandle); KiAcquireProcessLock(Process, &LockHandle);
/* Enter a critical region */
KeEnterCriticalRegion();
/* Loop the Process's Threads */ /* Loop the Process's Threads */
ListHead = &Process->ThreadListHead; ListHead = &Process->ThreadListHead;
NextEntry = ListHead->Flink; NextEntry = ListHead->Flink;
while (NextEntry != ListHead) do
{ {
/* Get the current thread */ /* Get the current thread */
Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry); Current = CONTAINING_RECORD(NextEntry, KTHREAD, ThreadListEntry);
@ -634,7 +631,7 @@ KeThawAllThreads(VOID)
/* Go to the next one */ /* Go to the next one */
NextEntry = NextEntry->Flink; NextEntry = NextEntry->Flink;
} } while (NextEntry != ListHead);
/* Release the process lock and exit the dispatcher */ /* Release the process lock and exit the dispatcher */
KiReleaseProcessLock(&LockHandle); KiReleaseProcessLock(&LockHandle);
@ -656,7 +653,6 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
/* Lock the Dispatcher Database and the APC Queue */ /* Lock the Dispatcher Database and the APC Queue */
KiAcquireApcLock(Thread, &ApcLock); KiAcquireApcLock(Thread, &ApcLock);
KiAcquireDispatcherLockAtDpcLevel();
/* Save the old State */ /* Save the old State */
OldState = Thread->Alerted[AlertMode]; OldState = Thread->Alerted[AlertMode];
@ -675,9 +671,7 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
} }
/* Release Locks and return the Old State */ /* Release Locks and return the Old State */
KiReleaseDispatcherLockFromDpcLevel(); KiReleaseApcLock(&ApcLock);
KiReleaseApcLockFromDpcLevel(&ApcLock);
KiExitDispatcher(ApcLock.OldIrql);
return OldState; return OldState;
} }
@ -718,7 +712,8 @@ KeInitThread(IN OUT PKTHREAD Thread,
Thread->EnableStackSwap = FALSE;//TRUE; Thread->EnableStackSwap = FALSE;//TRUE;
Thread->IdealProcessor = 1; Thread->IdealProcessor = 1;
Thread->SwapBusy = FALSE; Thread->SwapBusy = FALSE;
Thread->AdjustReason = 0; Thread->KernelStackResident = TRUE;
Thread->AdjustReason = AdjustNone;
/* Initialize the lock */ /* Initialize the lock */
KeInitializeSpinLock(&Thread->ThreadLock); KeInitializeSpinLock(&Thread->ThreadLock);
@ -1020,10 +1015,10 @@ KeSetIdealProcessorThread(IN PKTHREAD Thread,
OldIdealProcessor = Thread->UserIdealProcessor; OldIdealProcessor = Thread->UserIdealProcessor;
/* Make sure a valid CPU was given */ /* Make sure a valid CPU was given */
if (Processor < MAXIMUM_PROCESSORS) if (Processor < KeNumberProcessors)
{ {
/* Check if the user ideal CPU is in the affinity */ /* 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 */ /* Set the ideal processor */
Thread->IdealProcessor = Processor; Thread->IdealProcessor = Processor;
@ -1197,7 +1192,8 @@ KeSetBasePriorityThread(IN PKTHREAD Thread,
else else
{ {
/* Otherwise, calculate the new priority */ /* Otherwise, calculate the new priority */
Priority = KiComputeNewPriority(Thread); Priority = KiComputeNewPriority(Thread, 0);
Priority += (BasePriority - OldBasePriority);
/* Check if it entered the real-time range */ /* Check if it entered the real-time range */
if (Priority >= LOW_REALTIME_PRIORITY) if (Priority >= LOW_REALTIME_PRIORITY)
@ -1205,6 +1201,11 @@ KeSetBasePriorityThread(IN PKTHREAD Thread,
/* Normalize it down to the highest dynamic priority */ /* Normalize it down to the highest dynamic priority */
Priority = LOW_REALTIME_PRIORITY - 1; Priority = LOW_REALTIME_PRIORITY - 1;
} }
else if (Priority <= LOW_PRIORITY)
{
/* It went too low, normalize it */
Priority = 1;
}
} }
} }
@ -1291,6 +1292,7 @@ KeSetPriorityThread(IN PKTHREAD Thread,
ASSERT_THREAD(Thread); ASSERT_THREAD(Thread);
ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL); ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
ASSERT((Priority <= HIGH_PRIORITY) && (Priority >= LOW_PRIORITY)); ASSERT((Priority <= HIGH_PRIORITY) && (Priority >= LOW_PRIORITY));
ASSERT(KeIsExecutingDpc() == FALSE);
/* Lock the Dispatcher Database */ /* Lock the Dispatcher Database */
OldIrql = KiAcquireDispatcherLock(); OldIrql = KiAcquireDispatcherLock();
@ -1298,15 +1300,18 @@ KeSetPriorityThread(IN PKTHREAD Thread,
/* Lock the thread */ /* Lock the thread */
KiAcquireThreadLock(Thread); KiAcquireThreadLock(Thread);
/* Save the old Priority */ /* Save the old Priority and reset decrement */
OldPriority = Thread->Priority; OldPriority = Thread->Priority;
Thread->PriorityDecrement = 0;
/* Make sure that an actual change is being done */ /* Make sure that an actual change is being done */
if (OldPriority != Priority) if (Priority != Thread->Priority)
{ {
/* Reset the Quantum and Decrements */ /* Reset the quantum */
Thread->Quantum = Thread->QuantumReset; 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 */ /* Set the new Priority */
KiSetPriorityThread(Thread, Priority, &Released); KiSetPriorityThread(Thread, Priority, &Released);
@ -1417,7 +1422,7 @@ KeTerminateThread(IN KPRIORITY Increment)
ASSERT(Process->StackCount != 0); ASSERT(Process->StackCount != 0);
ASSERT(Process->State == ProcessInMemory); ASSERT(Process->State == ProcessInMemory);
Process->StackCount--; Process->StackCount--;
if (!Process->StackCount) if (!(Process->StackCount) && !(IsListEmpty(&Process->ThreadListHead)))
{ {
/* FIXME: Swap stacks */ /* FIXME: Swap stacks */
} }

View file

@ -252,11 +252,15 @@ VOID
STDCALL STDCALL
KiAdjustQuantumThread(IN PKTHREAD Thread) KiAdjustQuantumThread(IN PKTHREAD Thread)
{ {
KPRIORITY Priority; PKPRCB Prcb = KeGetCurrentPrcb();
/* Acquire thread and PRCB lock */
KiAcquireThreadLock(Thread);
KiAcquirePrcbLock(Prcb);
/* Don't adjust for RT threads */ /* Don't adjust for RT threads */
if ((Thread->Priority < LOW_REALTIME_PRIORITY) && 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 */ /* Decrease Quantum by one and see if we've ran out */
if (--Thread->Quantum <= 0) if (--Thread->Quantum <= 0)
@ -265,46 +269,45 @@ KiAdjustQuantumThread(IN PKTHREAD Thread)
Thread->Quantum = Thread->QuantumReset; Thread->Quantum = Thread->QuantumReset;
/* Calculate new Priority */ /* Calculate new Priority */
Priority = Thread->Priority - (Thread->PriorityDecrement + 1); Thread->Priority = KiComputeNewPriority(Thread, 1);
/* Normalize it if we've gone too low */ #ifdef NEW_SCHEDULER
if (Priority < Thread->BasePriority) Priority = Thread->BasePriority; /* Check if there's no next thread scheduled */
if (!Prcb->NextThread)
/* Reset the priority decrement, we've done it */
Thread->PriorityDecrement = 0;
/* Set the new priority, if needed */
if (Priority != Thread->Priority)
{ {
/* /* Select a new thread and set it on standby */
* FIXME: This should be a call to KiSetPriorityThread but NextThread = KiSelectNextThread(Prcb);
* due to the current ""scheduler"" in ROS, it can't be done NextThread->State = Standby;
* cleanly since it actualyl dispatches threads instead. Prcb->NextThread = NextThread;
*/
Thread->Priority = (SCHAR)Priority;
} }
else else
{ {
/* FIXME: Priority hasn't changed, find a new thread */ /* This thread can be preempted again */
Thread->Preempted = FALSE;
} }
#else
/* We need to dispatch a new thread */
KiDispatchThread(Ready);
#endif
} }
} }
/* Nothing to do... */ /* Release locks */
return; KiReleasePrcbLock(Prcb);
KiReleaseThreadLock(Thread);
} }
VOID VOID
STDCALL STDCALL
KiSetPriorityThread(PKTHREAD Thread, KiSetPriorityThread(IN PKTHREAD Thread,
KPRIORITY Priority, IN KPRIORITY Priority,
PBOOLEAN Released) OUT PBOOLEAN Released)
{ {
KPRIORITY OldPriority = Thread->Priority; KPRIORITY OldPriority = Thread->Priority;
ULONG Mask; ULONG Mask;
int i; ULONG i;
PKPCR Pcr; PKPCR Pcr;
DPRINT("Changing prio to : %lx\n", Priority); ASSERT((Priority >= 0) && (Priority <= HIGH_PRIORITY));
/* Check if priority changed */ /* Check if priority changed */
if (OldPriority != Priority) if (OldPriority != Priority)
@ -459,3 +462,4 @@ NtYieldExecution(VOID)
return STATUS_SUCCESS; return STATUS_SUCCESS;
} }