- Initialize the used page count for the non paged pool in MmInitializeBalancer.
[reactos.git] / reactos / ntoskrnl / mm / balance.c
index 40d069d..1543fd5 100644 (file)
@@ -16,7 +16,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
-/* $Id: balance.c,v 1.11 2002/08/14 20:58:36 dwelch Exp $
+/* $Id: balance.c,v 1.22 2003/10/23 20:28:08 hbirr Exp $
  *
  * PROJECT:     ReactOS kernel 
  * FILE:        ntoskrnl/mm/balance.c
@@ -59,24 +59,21 @@ static ULONG MiNrAvailablePages;
 static ULONG MiNrTotalPages;
 static LIST_ENTRY AllocationListHead;
 static KSPIN_LOCK AllocationListLock;
-static ULONG NrWorkingThreads = 0;
-static HANDLE WorkerThreadId;
 static ULONG MiPagesRequired = 0;
-static ULONG MiMinimumPagesPerRun = 1;
+static ULONG MiMinimumPagesPerRun = 10;
 
 /* FUNCTIONS ****************************************************************/
 
 VOID MmPrintMemoryStatistic(VOID)
 {
-  DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d\n",
-           MiMemoryConsumers[MC_CACHE].PagesUsed, 
-          MiMemoryConsumers[MC_USER].PagesUsed, 
-           MiMemoryConsumers[MC_PPOOL].PagesUsed, 
-          MiMemoryConsumers[MC_NPPOOL].PagesUsed); 
+  DbgPrint("MC_CACHE %d, MC_USER %d, MC_PPOOL %d, MC_NPPOOL %d, MiNrAvailablePages %d\n",
+           MiMemoryConsumers[MC_CACHE].PagesUsed, MiMemoryConsumers[MC_USER].PagesUsed, 
+           MiMemoryConsumers[MC_PPOOL].PagesUsed, MiMemoryConsumers[MC_NPPOOL].PagesUsed,
+          MiNrAvailablePages); 
 }
 
-VOID
-MmInitializeBalancer(ULONG NrAvailablePages)
+VOID INIT_FUNCTION
+MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
 {
   memset(MiMemoryConsumers, 0, sizeof(MiMemoryConsumers));
   InitializeListHead(&AllocationListHead);
@@ -91,9 +88,10 @@ MmInitializeBalancer(ULONG NrAvailablePages)
     NrAvailablePages - MiMinimumAvailablePages;
   MiMemoryConsumers[MC_PPOOL].PagesTarget = NrAvailablePages / 2;
   MiMemoryConsumers[MC_NPPOOL].PagesTarget = 0xFFFFFFFF;
+  MiMemoryConsumers[MC_NPPOOL].PagesUsed = NrSystemPages;
 }
 
-VOID
+VOID INIT_FUNCTION
 MmInitializeMemoryConsumer(ULONG Consumer, 
                           NTSTATUS (*Trim)(ULONG Target, ULONG Priority, 
                                            PULONG NrFreed))
@@ -111,15 +109,14 @@ MmReleasePageMemoryConsumer(ULONG Consumer, PHYSICAL_ADDRESS Page)
   if (Page.QuadPart == 0LL)
     {
       DPRINT1("Tried to release page zero.\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
 
   KeAcquireSpinLock(&AllocationListLock, &oldIrql);
   if (MmGetReferenceCountPage(Page) == 1)
     {
-      InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
-      InterlockedIncrement(&MiNrAvailablePages);
-      InterlockedDecrement(&MiPagesRequired);
+      InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
+      InterlockedIncrement((LONG *)&MiNrAvailablePages);
       if (IsListEmpty(&AllocationListHead))
        {
          KeReleaseSpinLock(&AllocationListLock, oldIrql);
@@ -151,7 +148,7 @@ MiTrimMemoryConsumer(ULONG Consumer)
 
   Target = MiMemoryConsumers[Consumer].PagesUsed - 
     MiMemoryConsumers[Consumer].PagesTarget;
-  if (Target < 0)
+  if (Target < 1)
     {
       Target = 1;
     }
@@ -163,7 +160,7 @@ MiTrimMemoryConsumer(ULONG Consumer)
 }
 
 VOID
-MiRebalanceMemoryConsumers(VOID)
+MmRebalanceMemoryConsumers(VOID)
 {
   LONG Target;
   ULONG i;
@@ -171,7 +168,7 @@ MiRebalanceMemoryConsumers(VOID)
   NTSTATUS Status;
 
   Target = (MiMinimumAvailablePages - MiNrAvailablePages) + MiPagesRequired;
-  Target = min(Target, MiMinimumPagesPerRun);
+  Target = max(Target, (LONG) MiMinimumPagesPerRun);
 
   for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
     {
@@ -180,15 +177,11 @@ MiRebalanceMemoryConsumers(VOID)
          Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages);
          if (!NT_SUCCESS(Status))
            {
-             KeBugCheck(0);
+             KEBUGCHECK(0);
            }
          Target = Target - NrFreedPages;
        }
     }
-  if (Target > 0)
-    {
-      KeBugCheck(0);
-    }
 }
 
 NTSTATUS
@@ -203,13 +196,13 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
   /*
    * Make sure we don't exceed our individual target.
    */
-  OldUsed = InterlockedIncrement(&MiMemoryConsumers[Consumer].PagesUsed);
+  OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
   if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
-      WorkerThreadId != PsGetCurrentThreadId())
+      !MiIsPagerThread())
     {
       if (!CanWait)
        {
-         InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
+         InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
          return(STATUS_NO_MEMORY);
        }
       MiTrimMemoryConsumer(Consumer);
@@ -218,77 +211,71 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
   /*
    * Make sure we don't exceed global targets.
    */
-  OldAvailable = InterlockedDecrement(&MiNrAvailablePages);
+  OldAvailable = InterlockedDecrement((LONG *)&MiNrAvailablePages);
   if (OldAvailable < MiMinimumAvailablePages)
     {
       MM_ALLOCATION_REQUEST Request;
 
       if (!CanWait)
        {
-         InterlockedIncrement(&MiNrAvailablePages);
-         InterlockedDecrement(&MiMemoryConsumers[Consumer].PagesUsed);
+         InterlockedIncrement((LONG *)&MiNrAvailablePages);
+         InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
          return(STATUS_NO_MEMORY);
        }
 
       /* Insert an allocation request. */
       Request.Page.QuadPart = 0LL;
       KeInitializeEvent(&Request.Event, NotificationEvent, FALSE);
-      InterlockedIncrement(&MiPagesRequired);
+      InterlockedIncrement((LONG *)&MiPagesRequired);
 
       KeAcquireSpinLock(&AllocationListLock, &oldIrql);     
-      if (NrWorkingThreads == 0)
+      /* Always let the pager thread itself allocate memory. */
+      if (MiIsPagerThread())
        {
-         InsertTailList(&AllocationListHead, &Request.ListEntry);
-         NrWorkingThreads++;
+         Page = MmAllocPage(Consumer, 0);
          KeReleaseSpinLock(&AllocationListLock, oldIrql);
-         WorkerThreadId = PsGetCurrentThreadId();
-         MiRebalanceMemoryConsumers();
-         KeAcquireSpinLock(&AllocationListLock, &oldIrql);
-         NrWorkingThreads--;
-         WorkerThreadId = 0;
-         KeReleaseSpinLock(&AllocationListLock, oldIrql);
-       }
-      else
-       {
-         if (WorkerThreadId == PsGetCurrentThreadId())
+         if (Page.QuadPart == 0LL)
            {
-             Page = MmAllocPage(Consumer, 0);
-             KeReleaseSpinLock(&AllocationListLock, oldIrql);
-             if (Page.QuadPart == 0LL)
-               {
-                 KeBugCheck(0);
-               }
-             *AllocatedPage = Page;
-             return(STATUS_SUCCESS);
+             KEBUGCHECK(0);
            }
-         InsertTailList(&AllocationListHead, &Request.ListEntry);
-         KeReleaseSpinLock(&AllocationListLock, oldIrql);
+         *AllocatedPage = Page;
+         InterlockedDecrement((LONG *)&MiPagesRequired);
+         return(STATUS_SUCCESS);
        }
+      /* Otherwise start the pager thread if it isn't already working. */
+      MiStartPagerThread();
+      InsertTailList(&AllocationListHead, &Request.ListEntry);
+      KeReleaseSpinLock(&AllocationListLock, oldIrql);
+
       KeWaitForSingleObject(&Request.Event,
                            0,
                            KernelMode,
                            FALSE,
                            NULL);
-
+      
       Page = Request.Page;
       if (Page.QuadPart == 0LL)
        {
-         KeBugCheck(0);
+         KEBUGCHECK(0);
        }
       MmTransferOwnershipPage(Page, Consumer);
       *AllocatedPage = Page;
+      InterlockedDecrement((LONG *)&MiPagesRequired);
+      MiStopPagerThread();
       return(STATUS_SUCCESS);
     }
-
+  
   /*
    * Actually allocate the page.
    */
   Page = MmAllocPage(Consumer, 0);
   if (Page.QuadPart == 0LL)
     {
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
   *AllocatedPage = Page;
 
   return(STATUS_SUCCESS);
 }
+
+/* EOF */