[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / mm / balance.c
index 17edb8e..9a65e26 100644 (file)
@@ -62,7 +62,7 @@ MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
    MiMinimumAvailablePages = 64;
     if ((NrAvailablePages + NrSystemPages) >= 8192)
     {
-        MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3;   
+        MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3;
     }
     else if ((NrAvailablePages + NrSystemPages) >= 4096)
     {
@@ -70,7 +70,7 @@ MmInitializeBalancer(ULONG NrAvailablePages, ULONG NrSystemPages)
     }
     else
     {
-        MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 8;        
+        MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 8;
     }
    MiMemoryConsumers[MC_USER].PagesTarget = NrAvailablePages - MiMinimumAvailablePages;
 }
@@ -131,7 +131,6 @@ MmReleasePageMemoryConsumer(ULONG Consumer, PFN_NUMBER Page)
    else
    {
       KeReleaseSpinLock(&AllocationListLock, OldIrql);
-      if(Consumer == MC_USER) MmRemoveLRUUserPage(Page);
       OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
       MmDereferencePage(Page);
       KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
@@ -147,12 +146,9 @@ MiTrimMemoryConsumer(ULONG Consumer)
    LONG Target;
    ULONG NrFreedPages;
 
-   Target = MiMemoryConsumers[Consumer].PagesUsed -
-            MiMemoryConsumers[Consumer].PagesTarget;
-   if (Target < 1)
-   {
-      Target = 1;
-   }
+   Target = max(MiMinimumPagesPerRun,
+                MiMemoryConsumers[Consumer].PagesUsed -
+                MiMemoryConsumers[Consumer].PagesTarget);
 
    if (MiMemoryConsumers[Consumer].Trim != NULL)
    {
@@ -166,14 +162,12 @@ MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
     PFN_NUMBER CurrentPage;
     PFN_NUMBER NextPage;
     NTSTATUS Status;
-    
+
     (*NrFreedPages) = 0;
-    
+
     CurrentPage = MmGetLRUFirstUserPage();
     while (CurrentPage != 0 && Target > 0)
     {
-        NextPage = MmGetLRUNextUserPage(CurrentPage);
-        
         Status = MmPageOutPhysicalAddress(CurrentPage);
         if (NT_SUCCESS(Status))
         {
@@ -181,10 +175,17 @@ MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
             Target--;
             (*NrFreedPages)++;
         }
-        
+
+        NextPage = MmGetLRUNextUserPage(CurrentPage);
+        if (NextPage <= CurrentPage)
+        {
+            /* We wrapped around, so we're done */
+            break;
+        }
         CurrentPage = NextPage;
     }
-    return(STATUS_SUCCESS);
+
+    return STATUS_SUCCESS;
 }
 
 VOID
@@ -196,7 +197,7 @@ MmRebalanceMemoryConsumers(VOID)
    ULONG NrFreedPages;
    NTSTATUS Status;
 
-   Target = (MiMinimumAvailablePages - MmAvailablePages) + MiPagesRequired;
+   Target = (ULONG)(MiMinimumAvailablePages - MmAvailablePages) + MiPagesRequired;
    Target = max(Target, (LONG) MiMinimumPagesPerRun);
 
    for (i = 0; i < MC_MAXIMUM && Target > 0; i++)
@@ -216,8 +217,8 @@ MmRebalanceMemoryConsumers(VOID)
 static BOOLEAN
 MiIsBalancerThread(VOID)
 {
-   return MiBalancerThreadHandle != NULL &&
-          PsGetCurrentThread() == MiBalancerThreadId.UniqueThread;
+   return (MiBalancerThreadHandle != NULL) &&
+          (PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread);
 }
 
 NTSTATUS
@@ -256,9 +257,11 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
       {
          KeBugCheck(NO_PAGES_AVAILABLE);
       }
+      if (Consumer == MC_USER) MmInsertLRULastUserPage(Page);
       *AllocatedPage = Page;
       if (MmAvailablePages <= MiMinimumAvailablePages &&
-            MiBalancerThreadHandle != NULL)
+          MiBalancerThreadHandle != NULL &&
+          !MiIsBalancerThread())
       {
          KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
       }
@@ -304,10 +307,18 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
       {
          KeBugCheck(NO_PAGES_AVAILABLE);
       }
-      /* Update the Consumer and make the page active */
+
       if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
       *AllocatedPage = Page;
       (void)InterlockedDecrementUL(&MiPagesRequired);
+       
+      if (MmAvailablePages <= MiMinimumAvailablePages &&
+          MiBalancerThreadHandle != NULL &&
+          !MiIsBalancerThread())
+      {
+          KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
+      }
+
       return(STATUS_SUCCESS);
    }
 
@@ -323,6 +334,13 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
    }
    if(Consumer == MC_USER) MmInsertLRULastUserPage(Page);
    *AllocatedPage = Page;
+    
+   if (MmAvailablePages <= MiMinimumAvailablePages &&
+       MiBalancerThreadHandle != NULL &&
+       !MiIsBalancerThread())
+   {
+       KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE);
+   }
 
    return(STATUS_SUCCESS);
 }