balmgr.c MS and ReactOS

Created Diff never expires
174 removals
189 lines
98 additions
114 lines
NTOS Kernel
REACT OS


VOID
VOID
KiScanReadyQueues (
NTAPI
IN PKDPC Dpc,
KiScanReadyQueues(IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2
IN PVOID SystemArgument2)
)

/*++
Routine Description:
This function scans a section of the ready queues and attempts to
boost the priority of threads that run at variable priority levels.
N.B. This function is executed as a DPC from the periodic timer that
drives the balance set manager.
Arguments:
Dpc - Supplies a pointer to a DPC object - not used.
DeferredContext - Supplies the DPC context - not used.
SystemArgument1 - Supplies the first system argument - note used.
SystemArgument2 - Supplies the second system argument - note used.
Return Value:
None.
--*/

{
{

PULONG ScanLast = DeferredContext;
ULONG Count = 0;
ULONG ScanIndex = *ScanLast;
PLIST_ENTRY Entry;
ULONG Count = 10, Number = 16;
ULONG Index;
PKPRCB Prcb = KiProcessorBlock[ScanIndex];
PLIST_ENTRY ListHead;
ULONG Index = Prcb->QueueIndex;
ULONG Number = 0;
ULONG WaitLimit = KeTickCount.LowPart - 300;
ULONG Summary;
KIRQL OldIrql;
KIRQL OldIrql;
PKPRCB Prcb;
PLIST_ENTRY ListHead, NextEntry;
ULONG ScanIndex;
PULONG ScanLast;
ULONG Summary;
PKTHREAD Thread;
PKTHREAD Thread;
ULONG WaitLimit;


UNREFERENCED_PARAMETER(SystemArgument1);
/* Lock the dispatcher and PRCB */
UNREFERENCED_PARAMETER(SystemArgument2);
OldIrql = KiAcquireDispatcherLock();

//
// Get the address of the queue index variable.
//
// N.B. If a fault occurs accessing queue index value, then the exception
// handler is either executed or a bugcheck occurs.
//

ScanLast = (PULONG)DeferredContext;

#if defined(_AMD64_)

try {
ScanIndex = *ScanLast;

} except(KiKernelDpcFilter(Dpc, GetExceptionInformation())) {
return;
}

#else

UNREFERENCED_PARAMETER(Dpc);

ScanIndex = *ScanLast;

#endif

//
// Lock the dispatcher database, acquire the PRCB lock, and check if
// there are any ready threads queued at the scanable priority levels.
//

Count = THREAD_READY_COUNT;
Number = THREAD_SCAN_COUNT;
Prcb = KiProcessorBlock[ScanIndex];
Index = Prcb->QueueIndex;
WaitLimit = KiQueryLowTickCount() - READY_WITHOUT_RUNNING;
KiLockDispatcherDatabase(&OldIrql);
KiAcquirePrcbLock(Prcb);
KiAcquirePrcbLock(Prcb);
/* Check if there's any thread that need help */
Summary = Prcb->ReadySummary & ((1 << THREAD_BOOST_PRIORITY) - 2);
Summary = Prcb->ReadySummary & ((1 << THREAD_BOOST_PRIORITY) - 2);
if (Summary != 0) {
if (Summary)
do {
{
/* Start scan loop */
do
{
/* Normalize the index */
if (Index > (THREAD_BOOST_PRIORITY - 1)) Index = 1;


//
/* Loop for ready threads */
// If the current ready queue index is beyond the end of the range
if (Summary & PRIORITY_MASK(Index))
// of priorities that are scanned, then wrap back to the beginning
{
// priority.
/* Sanity check */
//
ASSERT(!IsListEmpty(&Prcb->DispatcherReadyListHead[Index]));

if (Index > THREAD_SCAN_PRIORITY) {
Index = 1;
}


//
/* Update summary and select list */
// If there are any ready threads queued at the current priority
// level, then attempt to boost the thread priority.
//

if (Summary & PRIORITY_MASK(Index)) {

ASSERT(IsListEmpty(&Prcb->DispatcherReadyListHead[Index]) == FALSE);

Summary ^= PRIORITY_MASK(Index);
Summary ^= PRIORITY_MASK(Index);
ListHead = &Prcb->DispatcherReadyListHead[Index];
ListHead = &Prcb->DispatcherReadyListHead[Index];
Entry = ListHead->Flink;
NextEntry = ListHead->Flink;
do {
do

{
//
/* Select a thread */
// If the thread has been waiting for an extended period,
Thread = CONTAINING_RECORD(NextEntry,
// then boost the priority of the selected.
KTHREAD,
//
WaitListEntry);

ASSERT(Thread->Priority == Index);
Thread = CONTAINING_RECORD(Entry, KTHREAD, WaitListEntry);

ASSERT(Thread->Priority == (KPRIORITY)Index);

if (WaitLimit >= Thread->WaitTime) {

//
// Remove the thread from the respective ready queue.
//

Entry = Entry->Blink;

ASSERT((Prcb->ReadySummary & PRIORITY_MASK(Index)) != 0);


if (RemoveEntryList(Entry->Flink) != FALSE) {
/* Check if the thread has been waiting too long */
if (WaitLimit >= Thread->WaitTime)
{
/* Remove the thread from the queue */
NextEntry = NextEntry->Blink;
ASSERT((Prcb->ReadySummary & PRIORITY_MASK(Index)));
if (RemoveEntryList(NextEntry->Flink))
{
/* The list is empty now */
Prcb->ReadySummary ^= PRIORITY_MASK(Index);
Prcb->ReadySummary ^= PRIORITY_MASK(Index);
}
}


//
/* Verify priority decrement and set the new one */
// Compute the priority decrement value, set the new
// thread priority, set the thread quantum to a value
// appropriate for lock ownership, and insert the
// thread in the ready list.
//

ASSERT((Thread->PriorityDecrement >= 0) &&
ASSERT((Thread->PriorityDecrement >= 0) &&
(Thread->PriorityDecrement <= Thread->Priority));
(Thread->PriorityDecrement <=

Thread->Priority));
Thread->PriorityDecrement +=
Thread->PriorityDecrement += (THREAD_BOOST_PRIORITY -
(THREAD_BOOST_PRIORITY - Thread->Priority);
Thread->Priority);

ASSERT((Thread->PriorityDecrement >= 0) &&
ASSERT((Thread->PriorityDecrement >= 0) &&
(Thread->PriorityDecrement <= THREAD_BOOST_PRIORITY));
(Thread->PriorityDecrement <=
THREAD_BOOST_PRIORITY));


/* Update priority and insert into ready list */
Thread->Priority = THREAD_BOOST_PRIORITY;
Thread->Priority = THREAD_BOOST_PRIORITY;
Thread->Quantum = LOCK_OWNERSHIP_QUANTUM;
Thread->Quantum = WAIT_QUANTUM_DECREMENT * 4;
KiInsertDeferredReadyList(Thread);
KiInsertDeferredReadyList(Thread);
Count -= 1;
Count --;
}
}


Entry = Entry->Flink;
/* Go to the next entry */
Number -= 1;
NextEntry = NextEntry->Flink;
} while ((Entry != ListHead) && (Number != 0) && (Count != 0));
Number--;
} while((NextEntry != ListHead) && (Number) && (Count));
}
}


Index += 1;
/* Increase index */
} while ((Summary != 0) && (Number != 0) && (Count != 0));
Index++;
} while ((Summary) && (Number) && (Count));
}
}


//
/* Release the locks and dispatcher */
// Release the PRCB lock, unlock the dispatcher database, and save the
// last ready queue index for the next scan.
//

KiReleasePrcbLock(Prcb);
KiReleasePrcbLock(Prcb);
KiUnlockDispatcherDatabase(OldIrql);
KiReleaseDispatcherLock(OldIrql);
if ((Count != 0) && (Number != 0)) {

/* Update the queue index for next time */
if ((Count) && (Number))
{
/* Reset the queue at index 1 */
Prcb->QueueIndex = 1;
Prcb->QueueIndex = 1;

}
} else {
else
{
/* Set the index we're in now */
Prcb->QueueIndex = Index;
Prcb->QueueIndex = Index;
}
}


//
/* Increment the CPU number for next time and normalize to CPU count */
// Increment the processor number.
ScanIndex++;
//
if (ScanIndex == KeNumberProcessors) ScanIndex = 0;

ScanIndex += 1;
if (ScanIndex == (ULONG)KeNumberProcessors) {
ScanIndex = 0;
}


/* Return the index */
*ScanLast = ScanIndex;
*ScanLast = ScanIndex;
return;
}
}