update for HEAD-2002110701
[reactos.git] / ntoskrnl / mm / kmap.c
index 6980931..ab48792 100644 (file)
  * One bit for each page in the kmalloc region
  *      If set then the page is used by a kmalloc block
  */
-static ULONG AllocMap[ALLOC_MAP_SIZE/32]={0,};
+static UCHAR AllocMapBuffer[ROUND_UP(ALLOC_MAP_SIZE, 8) / 8];
+static RTL_BITMAP AllocMap;
 static KSPIN_LOCK AllocMapLock;
-static ULONG AllocMapHint = 1;
+static ULONG AllocMapHint = 0;
 
 static PVOID NonPagedPoolBase;
 
@@ -38,15 +39,14 @@ VOID
 ExUnmapPage(PVOID Addr)
 {
    KIRQL oldIrql;
-   ULONG i = (Addr - NonPagedPoolBase) / PAGE_SIZE;
+   ULONG Base = (Addr - NonPagedPoolBase) / PAGE_SIZE;
    
    DPRINT("ExUnmapPage(Addr %x)\n",Addr);
-   DPRINT("i %x\n",i);
    
    MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE, NULL, NULL);
    KeAcquireSpinLock(&AllocMapLock, &oldIrql);   
-   AllocMap[i / 32] &= (~(1 << (i % 32)));
-   AllocMapHint = min(AllocMapHint, i);
+   RtlClearBits(&AllocMap, Base, 1);
+   AllocMapHint = min(AllocMapHint, Base);
    KeReleaseSpinLock(&AllocMapLock, oldIrql);
 }
 
@@ -99,35 +99,31 @@ PVOID
 ExAllocatePageWithPhysPage(PHYSICAL_ADDRESS PhysPage)
 {
    KIRQL oldlvl;
-   ULONG addr;
-   ULONG i;
+   PVOID Addr;
+   ULONG Base;
    NTSTATUS Status;
 
    KeAcquireSpinLock(&AllocMapLock, &oldlvl);
-   for (i = AllocMapHint; i < ALLOC_MAP_SIZE; i++)
-     {
-       if (!(AllocMap[i / 32] & (1 << (i % 32))))
-        {
-           DPRINT("i %x\n",i);
-           AllocMap[i / 32] |= (1 << (i % 32));
-           AllocMapHint = i + 1;
-           addr = (ULONG)(NonPagedPoolBase + (i*PAGE_SIZE));
-           Status = MmCreateVirtualMapping(NULL, 
-                                           (PVOID)addr, 
-                                           PAGE_READWRITE | PAGE_SYSTEM, 
-                                           PhysPage,
-                                           FALSE);
-           if (!NT_SUCCESS(Status))
-             {
-               DbgPrint("Unable to create virtual mapping\n");
-               KeBugCheck(0);
-             }
-           KeReleaseSpinLock(&AllocMapLock, oldlvl);
-           return((PVOID)addr);
-        }
-     }
+   Base = RtlFindClearBitsAndSet(&AllocMap, 1, AllocMapHint);
+   if (Base != 0xFFFFFFFF)
+   {
+      AllocMapHint = Base + 1;
+      KeReleaseSpinLock(&AllocMapLock, oldlvl);
+      Addr = NonPagedPoolBase + Base * PAGE_SIZE;
+      Status = MmCreateVirtualMapping(NULL, 
+                                     Addr, 
+                                     PAGE_READWRITE | PAGE_SYSTEM, 
+                                     PhysPage,
+                                     FALSE);
+      if (!NT_SUCCESS(Status))
+      {
+          DbgPrint("Unable to create virtual mapping\n");
+         KeBugCheck(0);
+      }
+      return Addr;
+   }
    KeReleaseSpinLock(&AllocMapLock, oldlvl);
-   return(NULL);
+   return NULL;
 }
 
 VOID 
@@ -135,6 +131,8 @@ MmInitKernelMap(PVOID BaseAddress)
 {
    NonPagedPoolBase = BaseAddress;
    KeInitializeSpinLock(&AllocMapLock);
+   RtlInitializeBitMap(&AllocMap, (PVOID)&AllocMapBuffer, ALLOC_MAP_SIZE);
+   RtlClearAllBits(&AllocMap);
 }
 
 VOID
@@ -142,21 +140,19 @@ MiFreeNonPagedPoolRegion(PVOID Addr, ULONG Count, BOOLEAN Free)
 {
   ULONG i;
   ULONG Base = (Addr - NonPagedPoolBase) / PAGE_SIZE;
-  ULONG Offset;
   KIRQL oldlvl;
   
-  KeAcquireSpinLock(&AllocMapLock, &oldlvl);
-  AllocMapHint = min(AllocMapHint, Base);
   for (i = 0; i < Count; i++)
-    {
-      Offset = Base + i;
-      AllocMap[Offset / 32] &= (~(1 << (Offset % 32)));       
+  {
       MmDeleteVirtualMapping(NULL, 
                             Addr + (i * PAGE_SIZE), 
                             Free, 
                             NULL, 
                             NULL);
-    }
+  }
+  KeAcquireSpinLock(&AllocMapLock, &oldlvl);
+  RtlClearBits(&AllocMap, Base, Count);
+  AllocMapHint = min(AllocMapHint, Base);
   KeReleaseSpinLock(&AllocMapLock, oldlvl);
 }
 
@@ -166,44 +162,21 @@ MiAllocNonPagedPoolRegion(ULONG nr_pages)
  * FUNCTION: Allocates a region of pages within the nonpaged pool area
  */
 {
-   unsigned int start = 0;
-   unsigned int length = 0;
-   unsigned int i,j;
+   ULONG Base;
    KIRQL oldlvl;
 
    KeAcquireSpinLock(&AllocMapLock, &oldlvl);
-   for (i=AllocMapHint; i<ALLOC_MAP_SIZE;i++)
-     {
-       if (!(AllocMap[i/32] & (1 << (i % 32))))
-         {
-            if (length == 0)
-              {
-                 start=i;
-                 length = 1;
-              }
-            else
-              {
-                 length++;
-              }
-            if (length==nr_pages)
-              {
-                AllocMapHint = start + length;
-                for (j=start;j<(start+length);j++)
-                  {
-                    AllocMap[j / 32] |= (1 << (j % 32));
-                  }
-                DPRINT("returning %x\n",((start*PAGE_SIZE)+NonPagedPoolBase));
-                KeReleaseSpinLock(&AllocMapLock, oldlvl);
-                return(((start*PAGE_SIZE)+NonPagedPoolBase));
-              }
-         }
-       else
-        {
-          start=0;
-          length=0;
-        }
-     }
-   DbgPrint("CRITICAL: Out of non-paged pool space\n");
-   KeBugCheck(0);
-   return(0);
+   Base = RtlFindClearBitsAndSet(&AllocMap, nr_pages, AllocMapHint);
+   if (Base == 0xFFFFFFFF)
+   {
+      DbgPrint("CRITICAL: Out of non-paged pool space\n");
+      KeBugCheck(0);
+   }
+   if (AllocMapHint == Base)
+   {
+      AllocMapHint += nr_pages;
+   }
+   KeReleaseSpinLock(&AllocMapLock, oldlvl);
+   DPRINT("returning %x\n",NonPagedPoolBase + Base * PAGE_SIZE);
+   return NonPagedPoolBase + Base * PAGE_SIZE;
 }