update for HEAD-2003091401
[reactos.git] / ntoskrnl / mm / balance.c
index 753adae..6a9e689 100644 (file)
@@ -59,20 +59,17 @@ 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
@@ -111,7 +108,7 @@ MmReleasePageMemoryConsumer(ULONG Consumer, PHYSICAL_ADDRESS Page)
   if (Page.QuadPart == 0LL)
     {
       DPRINT1("Tried to release page zero.\n");
-      KeBugCheck(0);
+      KEBUGCHECK(0);
     }
 
   KeAcquireSpinLock(&AllocationListLock, &oldIrql);
@@ -119,7 +116,6 @@ MmReleasePageMemoryConsumer(ULONG Consumer, PHYSICAL_ADDRESS Page)
     {
       InterlockedDecrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
       InterlockedIncrement((LONG *)&MiNrAvailablePages);
-      InterlockedDecrement((LONG *)&MiPagesRequired);
       if (IsListEmpty(&AllocationListHead))
        {
          KeReleaseSpinLock(&AllocationListLock, oldIrql);
@@ -151,7 +147,7 @@ MiTrimMemoryConsumer(ULONG Consumer)
 
   Target = MiMemoryConsumers[Consumer].PagesUsed - 
     MiMemoryConsumers[Consumer].PagesTarget;
-  if (Target < 0)
+  if (Target < 1)
     {
       Target = 1;
     }
@@ -163,7 +159,7 @@ MiTrimMemoryConsumer(ULONG Consumer)
 }
 
 VOID
-MiRebalanceMemoryConsumers(VOID)
+MmRebalanceMemoryConsumers(VOID)
 {
   LONG Target;
   ULONG i;
@@ -171,7 +167,7 @@ MiRebalanceMemoryConsumers(VOID)
   NTSTATUS Status;
 
   Target = (MiMinimumAvailablePages - MiNrAvailablePages) + MiPagesRequired;
-  Target = min(Target, (LONG) MiMinimumPagesPerRun);
+  Target = max(Target, (LONG) MiMinimumPagesPerRun);
 
   for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
     {
@@ -180,15 +176,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
@@ -205,7 +197,7 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
    */
   OldUsed = InterlockedIncrement((LONG *)&MiMemoryConsumers[Consumer].PagesUsed);
   if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) &&
-      WorkerThreadId != PsGetCurrentThreadId())
+      !MiIsPagerThread())
     {
       if (!CanWait)
        {
@@ -236,59 +228,53 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
       InterlockedIncrement((LONG *)&MiPagesRequired);
 
       KeAcquireSpinLock(&AllocationListLock, &oldIrql);     
-      if (NrWorkingThreads == 0)
+      /* Always let the pager thread itself allocate memory. */
+      if (MiIsPagerThread())
        {
-         InsertTailList(&AllocationListHead, &Request.ListEntry);
-         NrWorkingThreads++;
-         KeReleaseSpinLock(&AllocationListLock, oldIrql);
-         WorkerThreadId = PsGetCurrentThreadId();
-         MiRebalanceMemoryConsumers();
-         KeAcquireSpinLock(&AllocationListLock, &oldIrql);
-         NrWorkingThreads--;
-         WorkerThreadId = 0;
+         Page = MmAllocPage(Consumer, 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 */