From 91d26f3e2309d175793844061cc6f3944fcac17f Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Thu, 25 Jan 2007 18:48:56 +0000 Subject: [PATCH] - Implement the balance set manager. Doesn't do much for now except start up the thread queue scanner. - Implement the thread queue scanner, but disable most of it for now, since we're not using the new scheduler. svn path=/trunk/; revision=25630 --- reactos/ntoskrnl/include/internal/ke.h | 4 + reactos/ntoskrnl/include/internal/mm.h | 4 + reactos/ntoskrnl/ke/apc.c | 2 +- reactos/ntoskrnl/ke/balmgr.c | 207 +++++++++++++++++++++++++ reactos/ntoskrnl/mm/mminit.c | 3 + reactos/ntoskrnl/mm/mpw.c | 23 +++ reactos/ntoskrnl/ntoskrnl.rbuild | 1 + 7 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 reactos/ntoskrnl/ke/balmgr.c diff --git a/reactos/ntoskrnl/include/internal/ke.h b/reactos/ntoskrnl/include/internal/ke.h index 14001887d16..05d58fa9f11 100644 --- a/reactos/ntoskrnl/include/internal/ke.h +++ b/reactos/ntoskrnl/include/internal/ke.h @@ -217,6 +217,10 @@ KeReadyThread( IN PKTHREAD Thread ); +VOID +NTAPI +KeBalanceSetManager(IN PVOID Context); + VOID NTAPI KiReadyThread(IN PKTHREAD Thread); diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 7f2d2502063..2c5f3e7ae92 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -1400,6 +1400,10 @@ NTSTATUS NTAPI MmInitMpwThread(VOID); +NTSTATUS +NTAPI +MmInitBsmThread(VOID); + /* pager.c *******************************************************************/ BOOLEAN diff --git a/reactos/ntoskrnl/ke/apc.c b/reactos/ntoskrnl/ke/apc.c index 8d4830a1c16..03ce65ad6e9 100644 --- a/reactos/ntoskrnl/ke/apc.c +++ b/reactos/ntoskrnl/ke/apc.c @@ -212,7 +212,7 @@ Unwait: { /* We were in a gate wait. FIXME: Handle this */ DPRINT1("Not yet supported -- Report this to Alex\n"); - KEBUGCHECK(0); + while (TRUE); } } else if ((Thread->State == Waiting) && diff --git a/reactos/ntoskrnl/ke/balmgr.c b/reactos/ntoskrnl/ke/balmgr.c new file mode 100644 index 00000000000..41e4988dc74 --- /dev/null +++ b/reactos/ntoskrnl/ke/balmgr.c @@ -0,0 +1,207 @@ +/* +* PROJECT: ReactOS Kernel +* LICENSE: GPL - See COPYING in the top level directory +* FILE: ntoskrnl/ke/balmgr.c +* PURPOSE: Balance Set Manager +* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) +*/ + +/* INCLUDES ******************************************************************/ + +#include +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define THREAD_BOOST_PRIORITY (LOW_REALTIME_PRIORITY - 1) +ULONG KiReadyScanLast; + +/* PRIVATE FUNCTIONS *********************************************************/ + +VOID +NTAPI +KiScanReadyQueues(IN PKDPC Dpc, + IN PVOID DeferredContext, + IN PVOID SystemArgument1, + IN PVOID SystemArgument2) +{ + PULONG ScanLast = DeferredContext; + ULONG ScanIndex = *ScanLast; + ULONG Count = 10, Number = 16; + PKPRCB Prcb = KiProcessorBlock[ScanIndex]; + ULONG Index = Prcb->QueueIndex; + ULONG WaitLimit = KeTickCount.LowPart - 300; + ULONG Summary; + KIRQL OldIrql; + PLIST_ENTRY ListHead, NextEntry; + PKTHREAD Thread; + + /* Lock the dispatcher and PRCB */ + OldIrql = KiAcquireDispatcherLock(); + KiAcquirePrcbLock(Prcb); +#ifndef NEW_SCHEDULER + goto OldSched; +#endif + + /* Check if there's any thread that need help */ + Summary = Prcb->ReadySummary & ((1 << THREAD_BOOST_PRIORITY) - 2); + if (Summary) + { + /* Start scan loop */ + do + { + /* Normalize the index */ + if (Index > (THREAD_BOOST_PRIORITY - 1)) Index = 1; + + /* Loop for ready threads */ + if (Summary & PRIORITY_MASK(Index)) + { + /* Sanity check */ + ASSERT(!IsListEmpty(&Prcb->DispatcherReadyListHead[Index])); + + /* Update summary and select list */ + Summary ^= PRIORITY_MASK(Index); + ListHead = &Prcb->DispatcherReadyListHead[Index]; + NextEntry = ListHead->Flink; + do + { + /* Select a thread */ + Thread = CONTAINING_RECORD(NextEntry, + KTHREAD, + WaitListEntry); + ASSERT(Thread->Priority == Index); + + /* 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); + } + + /* Verify priority decrement and set the new one */ + ASSERT((Thread->PriorityDecrement >= 0) && + (Thread->PriorityDecrement <= + Thread->Priority)); + Thread->PriorityDecrement += (THREAD_BOOST_PRIORITY - + Thread->Priority); + ASSERT((Thread->PriorityDecrement >= 0) && + (Thread->PriorityDecrement <= + THREAD_BOOST_PRIORITY)); + + /* Update priority and insert into ready list */ + Thread->Priority = THREAD_BOOST_PRIORITY; + Thread->Quantum = WAIT_QUANTUM_DECREMENT * 4; + KiInsertDeferredReadyList(Thread); + Count --; + } + + /* Go to the next entry */ + NextEntry = NextEntry->Flink; + Number--; + } while((NextEntry != ListHead) && (Number) && (Count)); + } + + /* Increase index */ + Index++; + } while ((Summary) && (Number) && (Count)); + } + + /* Release the locks and dispatcher */ +OldSched: + KiReleasePrcbLock(Prcb); + KiReleaseDispatcherLock(OldIrql); + + /* Update the queue index for next time */ + if ((Count) && (Number)) + { + /* Reset the queue at index 1 */ + Prcb->QueueIndex = 1; + } + else + { + /* Set the index we're in now */ + Prcb->QueueIndex = 0; + } + + /* Increment the CPU number for next time and normalize to CPU count */ + ScanIndex++; + if (ScanIndex == KeNumberProcessors) ScanIndex = 0; + + /* Return the index */ + *ScanLast = ScanIndex; +} + +VOID +NTAPI +KeBalanceSetManager(IN PVOID Context) +{ + KDPC ScanDpc; + KTIMER PeriodTimer; + LARGE_INTEGER DueTime; + KWAIT_BLOCK WaitBlockArray[1]; + PVOID WaitObjects[1]; + NTSTATUS Status; + + /* Set us at a low real-time priority level */ + KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY); + + /* Setup the timer and scanner DPC */ + KeInitializeTimerEx(&PeriodTimer, SynchronizationTimer); + KeInitializeDpc(&ScanDpc, KiScanReadyQueues, &KiReadyScanLast); + + /* Setup the periodic timer */ + DueTime.QuadPart = -1 * 10 * 1000 * 1000; + KeSetTimerEx(&PeriodTimer, DueTime, 1000, &ScanDpc); + + /* Setup the wait objects */ + WaitObjects[0] = &PeriodTimer; + //WaitObjects[1] = MmWorkingSetManagerEvent; // NO WS Management Yet! + + /* Start wait loop */ + do + { + /* Wait on our objects */ + Status = KeWaitForMultipleObjects(1, + WaitObjects, + WaitAny, + Executive, + KernelMode, + FALSE, + NULL, + WaitBlockArray); + switch (Status) + { + /* Check if our timer expired */ + case STATUS_WAIT_0: + + /* Adjust lookaside lists */ + //ExAdjustLookasideDepth(); + + /* Call the working set manager */ + //MmWorkingSetManager(); + + /* FIXME: Outswap stacks */ + + /* Done */ + break; + + /* Check if the working set manager notified us */ + case STATUS_WAIT_1: + + /* Call the working set manager */ + //MmWorkingSetManager(); + break; + + /* Anything else */ + default: + DPRINT1("BALMGR: Illegal wait status, %lx =\n", Status); + break; + } + } while (TRUE); +} diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index 8607291de1b..59895d072f3 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -482,6 +482,9 @@ MmInitSystem(IN ULONG Phase, */ MmInitMpwThread(); + /* Initialize the balance set manager */ + MmInitBsmThread(); + /* FIXME: Read parameters from memory */ } diff --git a/reactos/ntoskrnl/mm/mpw.c b/reactos/ntoskrnl/mm/mpw.c index be3db5898b7..95c04535016 100644 --- a/reactos/ntoskrnl/mm/mpw.c +++ b/reactos/ntoskrnl/mm/mpw.c @@ -123,3 +123,26 @@ MmInitMpwThread(VOID) return(STATUS_SUCCESS); } + +NTSTATUS +NTAPI +MmInitBsmThread(VOID) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE ThreadHandle; + + /* Create the thread */ + InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); + Status = PsCreateSystemThread(&ThreadHandle, + THREAD_ALL_ACCESS, + &ObjectAttributes, + NULL, + NULL, + KeBalanceSetManager, + NULL); + + /* Close the handle and return status */ + ZwClose(ThreadHandle); + return Status; +} diff --git a/reactos/ntoskrnl/ntoskrnl.rbuild b/reactos/ntoskrnl/ntoskrnl.rbuild index dd73ec5d4fc..600d0efae5a 100644 --- a/reactos/ntoskrnl/ntoskrnl.rbuild +++ b/reactos/ntoskrnl/ntoskrnl.rbuild @@ -47,6 +47,7 @@ apc.c + balmgr.c bug.c clock.c config.c