[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
FORCEINLINE
KiComputeNewPriority(IN PKTHREAD Thread)
KiComputeNewPriority(IN PKTHREAD Thread,
IN SCHAR Adjustment)
{
SCHAR Priority;
@ -1319,7 +1320,7 @@ KiComputeNewPriority(IN PKTHREAD Thread)
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;

View file

@ -39,7 +39,6 @@ VOID
NTAPI
KiQuantumEnd(VOID)
{
KPRIORITY Priority;
PKPRCB Prcb = KeGetCurrentPrcb();
PKTHREAD NextThread, Thread = Prcb->CurrentThread;
@ -66,7 +65,7 @@ KiQuantumEnd(VOID)
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 @@ KeInsertQueueDpc(IN PKDPC Dpc,
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 @@ KeInsertQueueDpc(IN PKDPC Dpc,
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)

View file

@ -237,7 +237,7 @@ KeSetEventBoostPriority(IN PKEVENT Event,
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 @@ KeSetEventBoostPriority(IN PKEVENT Event,
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);

View file

@ -134,7 +134,8 @@ KeAlertResumeThread(IN PKTHREAD Thread)
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 @@ KeAlertThread(IN PKTHREAD Thread,
{
/* 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 @@ KeFreezeAllThreads(VOID)
/* 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 @@ KeFreezeAllThreads(VOID)
/* 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 @@ KeRundownThread(VOID)
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 @@ KeStartThread(IN OUT PKTHREAD Thread)
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 @@ KeThawAllThreads(VOID)
/* 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 @@ KeThawAllThreads(VOID)
/* 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 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
/* Lock the Dispatcher Database and the APC Queue */
KiAcquireApcLock(Thread, &ApcLock);
KiAcquireDispatcherLockAtDpcLevel();
/* Save the old State */
OldState = Thread->Alerted[AlertMode];
@ -675,9 +671,7 @@ KeTestAlertThread(IN KPROCESSOR_MODE AlertMode)
}
/* Release Locks and return the Old State */
KiReleaseDispatcherLockFromDpcLevel();
KiReleaseApcLockFromDpcLevel(&ApcLock);
KiExitDispatcher(ApcLock.OldIrql);
KiReleaseApcLock(&ApcLock);
return OldState;
}
@ -718,7 +712,8 @@ KeInitThread(IN OUT PKTHREAD Thread,
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 @@ KeSetIdealProcessorThread(IN PKTHREAD Thread,
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 @@ KeSetBasePriorityThread(IN PKTHREAD Thread,
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 @@ KeSetBasePriorityThread(IN PKTHREAD Thread,
/* 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 @@ KeSetPriorityThread(IN PKTHREAD Thread,
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 @@ KeSetPriorityThread(IN PKTHREAD Thread,
/* 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)
if (Priority != Thread->Priority)
{
/* Reset the Quantum and Decrements */
/* 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 @@ KeTerminateThread(IN KPRIORITY Increment)
ASSERT(Process->StackCount != 0);
ASSERT(Process->State == ProcessInMemory);
Process->StackCount--;
if (!Process->StackCount)
if (!(Process->StackCount) && !(IsListEmpty(&Process->ThreadListHead)))
{
/* FIXME: Swap stacks */
}

View file

@ -252,11 +252,15 @@ VOID
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 @@ KiAdjustQuantumThread(IN PKTHREAD Thread)
Thread->Quantum = Thread->QuantumReset;
/* Calculate new Priority */
Priority = Thread->Priority - (Thread->PriorityDecrement + 1);
Thread->Priority = KiComputeNewPriority(Thread, 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)
#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 */
/* This thread can be preempted again */
Thread->Preempted = FALSE;
}
#else
/* We need to dispatch a new thread */
KiDispatchThread(Ready);
#endif
}
}
/* Nothing to do... */
return;
/* 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 @@ NtYieldExecution(VOID)
return STATUS_SUCCESS;
}