Change the MEMORY_AREAs to be stored it a binary search tree instead of linked list. Thanks to Royce Mitchell III and Mike Nordell for helping me.
Modified: trunk/reactos/ntoskrnl/cc/view.c
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
Modified: trunk/reactos/ntoskrnl/ke/bug.c
Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
Modified: trunk/reactos/ntoskrnl/ke/kthread.c
Modified: trunk/reactos/ntoskrnl/mm/anonmem.c
Modified: trunk/reactos/ntoskrnl/mm/aspace.c
Modified: trunk/reactos/ntoskrnl/mm/cont.c
Modified: trunk/reactos/ntoskrnl/mm/drvlck.c
Modified: trunk/reactos/ntoskrnl/mm/iospace.c
Modified: trunk/reactos/ntoskrnl/mm/marea.c
Modified: trunk/reactos/ntoskrnl/mm/mdl.c
Modified: trunk/reactos/ntoskrnl/mm/mm.c
Modified: trunk/reactos/ntoskrnl/mm/mminit.c
Modified: trunk/reactos/ntoskrnl/mm/ncache.c
Modified: trunk/reactos/ntoskrnl/mm/pe.c
Modified: trunk/reactos/ntoskrnl/mm/rmap.c
Modified: trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/mm/virtual.c
Modified: trunk/reactos/ntoskrnl/ps/w32call.c

Modified: trunk/reactos/ntoskrnl/cc/view.c
--- trunk/reactos/ntoskrnl/cc/view.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/cc/view.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -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: view.c,v 1.79 2004/10/22 20:11:12 ekohl Exp $
+/* $Id$
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/cc/view.c
@@ -813,8 +813,7 @@
 #else
   MmLockAddressSpace(MmGetKernelAddressSpace());
   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-		   CacheSeg->BaseAddress,
-		   CacheSeg->Bcb->CacheSegmentSize,
+		   CacheSeg->MemoryArea,
 		   CcFreeCachePage,
 		   NULL);
   MmUnlockAddressSpace(MmGetKernelAddressSpace());

Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
--- trunk/reactos/ntoskrnl/include/internal/mm.h	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h	2005-01-02 17:55:06 UTC (rev 12728)
@@ -184,15 +184,17 @@
 
 #endif /* __USE_W32API */
 
-typedef struct
+typedef struct _MEMORY_AREA
 {
+  PVOID StartingAddress;
+  PVOID EndingAddress;
+  struct _MEMORY_AREA *Parent;
+  struct _MEMORY_AREA *LeftChild;
+  struct _MEMORY_AREA *RightChild;
   ULONG Type;
-  PVOID BaseAddress;
-  ULONG Length;
   ULONG Attributes;
-  LIST_ENTRY Entry;
   ULONG LockCount;
-  struct _EPROCESS* Process;
+  struct _EPROCESS* Process; /* FIXME: We don't need this! */
   BOOLEAN DeleteInProgress;
   ULONG PageOpCount;
   union
@@ -215,7 +217,7 @@
 
 typedef struct _MADDRESS_SPACE
 {
-  LIST_ENTRY MAreaListHead;
+  PMEMORY_AREA MemoryAreaRoot;
   FAST_MUTEX Lock;
   PVOID LowestAddress;
   struct _EPROCESS* Process;
@@ -333,6 +335,10 @@
    LIST_ENTRY RegionListEntry;
 } MM_REGION, *PMM_REGION;
 
+typedef VOID (*PMM_FREE_PAGE_FUNC)(PVOID Context, PMEMORY_AREA MemoryArea, 
+                                   PVOID Address, PFN_TYPE Page,
+                                   SWAPENTRY SwapEntry, BOOLEAN Dirty);
+
 /* FUNCTIONS */
 
 /* aspace.c ******************************************************************/
@@ -354,49 +360,68 @@
 
 /* marea.c *******************************************************************/
 
-NTSTATUS MmCreateMemoryArea(struct _EPROCESS* Process,
-			    PMADDRESS_SPACE AddressSpace,
-			    ULONG Type,
-			    PVOID* BaseAddress,
-			    ULONG Length,
-			    ULONG Attributes,
-			    MEMORY_AREA** Result,
-			    BOOL FixedAddress,
-			    BOOL TopDown,
-			    PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL);
+NTSTATUS INIT_FUNCTION
+MmInitMemoryAreas(VOID);
 
-MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace, 
-				       PVOID Address);
+NTSTATUS STDCALL
+MmCreateMemoryArea(
+   struct _EPROCESS* Process,
+   PMADDRESS_SPACE AddressSpace,
+   ULONG Type,
+   PVOID *BaseAddress,
+   ULONG_PTR Length,
+   ULONG Attributes,
+   PMEMORY_AREA *Result,
+   BOOLEAN FixedAddress,
+   BOOLEAN TopDown,
+   PHYSICAL_ADDRESS BoundaryAddressMultiple OPTIONAL);
 
-ULONG MmFindGapAtAddress(PMADDRESS_SPACE AddressSpace, 
-			 PVOID Address);
+PMEMORY_AREA STDCALL
+MmOpenMemoryAreaByAddress(
+   PMADDRESS_SPACE AddressSpace, 
+   PVOID Address);
 
-NTSTATUS MmInitMemoryAreas(VOID);
+ULONG STDCALL
+MmFindGapAtAddress(
+   PMADDRESS_SPACE AddressSpace, 
+   PVOID Address);
 
-NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
-			  PVOID BaseAddress,
-			  ULONG Length,
-			  VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, 
-					   PVOID Address, PFN_TYPE Page, SWAPENTRY SwapEntry,
-					   BOOLEAN Dirty),
-			  PVOID FreePageContext);
+NTSTATUS STDCALL
+MmFreeMemoryArea(
+   PMADDRESS_SPACE AddressSpace,
+   PMEMORY_AREA MemoryArea,
+   PMM_FREE_PAGE_FUNC FreePage,
+   PVOID FreePageContext);
 
-VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead);
+NTSTATUS STDCALL
+MmFreeMemoryAreaByPtr(
+   PMADDRESS_SPACE AddressSpace,
+   PVOID BaseAddress,
+   PMM_FREE_PAGE_FUNC FreePage,
+   PVOID FreePageContext);
 
-NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea);
+VOID STDCALL
+MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace);
 
-NTSTATUS MmUnlockMemoryArea(MEMORY_AREA* MemoryArea);
+PMEMORY_AREA STDCALL
+MmOpenMemoryAreaByRegion(
+   PMADDRESS_SPACE AddressSpace, 
+   PVOID Address,
+   ULONG_PTR Length);
 
-MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace, 
-				      PVOID Address,
-				      ULONG Length);
+PVOID STDCALL
+MmFindGap(
+   PMADDRESS_SPACE AddressSpace,
+   ULONG_PTR Length,
+   ULONG_PTR Granularity,
+   BOOLEAN TopDown);
 
-PVOID MmFindGap(PMADDRESS_SPACE AddressSpace, ULONG Length, ULONG Granularity, BOOL TopDown);
+VOID STDCALL
+MmReleaseMemoryAreaIfDecommitted(
+   PEPROCESS Process,
+   PMADDRESS_SPACE AddressSpace,
+   PVOID BaseAddress);
 
-void MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process,
-                                      PMADDRESS_SPACE AddressSpace,
-                                      PVOID BaseAddress);
-
 /* npool.c *******************************************************************/
 
 VOID MiDebugDumpNonPagedPool(BOOLEAN NewOnly);

Modified: trunk/reactos/ntoskrnl/ke/bug.c
--- trunk/reactos/ntoskrnl/ke/bug.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/ke/bug.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -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: bug.c,v 1.48 2004/12/12 17:42:00 hbirr Exp $
+/* $Id$
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/ke/bug.c
@@ -116,6 +116,11 @@
   Ke386DisableInterrupts();
   DebugLogDumpMessages();
 
+  if (MmGetKernelAddressSpace()->Lock.Owner == KeGetCurrentThread())
+    {
+      MmUnlockAddressSpace(MmGetKernelAddressSpace());
+    }
+
   if (KeGetCurrentIrql() < DISPATCH_LEVEL)
     {
       KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);

Modified: trunk/reactos/ntoskrnl/ke/i386/exp.c
--- trunk/reactos/ntoskrnl/ke/i386/exp.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/ke/i386/exp.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -320,7 +320,7 @@
 	{
 	  KeRosPrintAddress((PVOID)Frame[1]);
 	  Frame = (PULONG)Frame[0];
-          DbgPrint(" ");
+          DbgPrint("\n");
 	}
 #else
       DbgPrint("Frames: ");
@@ -663,7 +663,7 @@
 				break;
 			StackBase = Frame;
 			Frame = (PULONG)Frame[0];
-			DbgPrint(" ");
+			DbgPrint("\n");
 		}
 	}
 	_SEH_HANDLE

Modified: trunk/reactos/ntoskrnl/ke/kthread.c
--- trunk/reactos/ntoskrnl/ke/kthread.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/ke/kthread.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -90,11 +90,10 @@
   if (Thread->StackLimit != (ULONG_PTR)&init_stack)
     {       
       MmLockAddressSpace(MmGetKernelAddressSpace());
-      MmFreeMemoryArea(MmGetKernelAddressSpace(),
-		       (PVOID)Thread->StackLimit,
-		       MM_STACK_SIZE,
-		       KeFreeStackPage,
-		       NULL);
+      MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                            (PVOID)Thread->StackLimit,
+                            KeFreeStackPage,
+                            NULL);
       MmUnlockAddressSpace(MmGetKernelAddressSpace());
     }
   Thread->StackLimit = 0;

Modified: trunk/reactos/ntoskrnl/mm/anonmem.c
--- trunk/reactos/ntoskrnl/mm/anonmem.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/mm/anonmem.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -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: anonmem.c,v 1.34 2004/12/19 16:16:57 navaraf Exp $
+/* $Id$
  *
  * PROJECT:     ReactOS kernel
  * FILE:        ntoskrnl/mm/anonmem.c
@@ -261,7 +261,7 @@
    /*
     * Get the segment corresponding to the virtual address
     */
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                          Address, NULL);
    if (Region->Type == MEM_RESERVE || Region->Protect == PAGE_NOACCESS)
@@ -525,6 +525,7 @@
 {
    PEPROCESS Process;
    MEMORY_AREA* MemoryArea;
+   ULONG_PTR MemoryAreaLength;
    ULONG Type;
    NTSTATUS Status;
    PMADDRESS_SPACE AddressSpace;
@@ -582,40 +583,44 @@
       MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
                                              BaseAddress);
 
-      if (MemoryArea != NULL &&
-            MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY &&
-            MemoryArea->Length >= RegionSize)
+      if (MemoryArea != NULL)
       {
-         Status =
-            MmAlterRegion(AddressSpace,
-                          MemoryArea->BaseAddress,
-                          &MemoryArea->Data.VirtualMemoryData.RegionListHead,
-                          BaseAddress, RegionSize,
-                          Type, Protect, MmModifyAttributes);
-         MmUnlockAddressSpace(AddressSpace);
-         ObDereferenceObject(Process);
-         DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
-         return(Status);
+         MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress -
+                            (ULONG_PTR)MemoryArea->StartingAddress;
+         if (MemoryArea->Type == MEMORY_AREA_VIRTUAL_MEMORY &&
+             MemoryAreaLength >= RegionSize)
+         {
+            Status =
+               MmAlterRegion(AddressSpace,
+                             MemoryArea->StartingAddress,
+                             &MemoryArea->Data.VirtualMemoryData.RegionListHead,
+                             BaseAddress, RegionSize,
+                             Type, Protect, MmModifyAttributes);
+            MmUnlockAddressSpace(AddressSpace);
+            ObDereferenceObject(Process);
+            DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
+            return(Status);
+         }
+         else if (MemoryAreaLength >= RegionSize)
+         {
+            Status =
+               MmAlterRegion(AddressSpace,
+                             MemoryArea->StartingAddress,
+                             &MemoryArea->Data.SectionData.RegionListHead,
+                             BaseAddress, RegionSize,
+                             Type, Protect, MmModifyAttributes);
+            MmUnlockAddressSpace(AddressSpace);
+            ObDereferenceObject(Process);
+            DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
+            return(Status);
+         }
+         else
+         {
+            MmUnlockAddressSpace(AddressSpace);
+            ObDereferenceObject(Process);
+            return(STATUS_UNSUCCESSFUL);
+         }
       }
-      else if (MemoryArea != NULL && MemoryArea->Length >= RegionSize)
-      {
-         Status =
-            MmAlterRegion(AddressSpace,
-                          MemoryArea->BaseAddress,
-                          &MemoryArea->Data.SectionData.RegionListHead,
-                          BaseAddress, RegionSize,
-                          Type, Protect, MmModifyAttributes);
-         MmUnlockAddressSpace(AddressSpace);
-         ObDereferenceObject(Process);
-         DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
-         return(Status);
-      }
-      else if (MemoryArea != NULL)
-      {
-         MmUnlockAddressSpace(AddressSpace);
-         ObDereferenceObject(Process);
-         return(STATUS_UNSUCCESSFUL);
-      }
    }
 
    Status = MmCreateMemoryArea(Process,
@@ -626,7 +631,7 @@
                                Protect,
                                &MemoryArea,
                                PBaseAddress != 0,
-                               (AllocationType & MEM_TOP_DOWN),
+                               (AllocationType & MEM_TOP_DOWN) == MEM_TOP_DOWN,
                                BoundaryAddressMultiple);
    if (!NT_SUCCESS(Status))
    {
@@ -635,18 +640,22 @@
       DPRINT("NtAllocateVirtualMemory() = %x\n",Status);
       return(Status);
    }
+
+   MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress -
+                      (ULONG_PTR)MemoryArea->StartingAddress;
+   
    MmInitialiseRegion(&MemoryArea->Data.VirtualMemoryData.RegionListHead,
-                      MemoryArea->Length, Type, Protect);
+                      MemoryAreaLength, Type, Protect);
 
    if ((AllocationType & MEM_COMMIT) &&
          ((Protect & PAGE_READWRITE) ||
           (Protect & PAGE_EXECUTE_READWRITE)))
    {
-      MmReserveSwapPages(MemoryArea->Length);
+      MmReserveSwapPages(MemoryAreaLength);
    }
 
    *UBaseAddress = BaseAddress;
-   *URegionSize = MemoryArea->Length;
+   *URegionSize = MemoryAreaLength;
    DPRINT("*UBaseAddress %x  *URegionSize %x\n", BaseAddress, RegionSize);
 
    MmUnlockAddressSpace(AddressSpace);
@@ -702,7 +711,11 @@
     */
    if (MemoryArea->PageOpCount > 0)
    {
-      for (i = 0; i < PAGE_ROUND_UP(MemoryArea->Length) / PAGE_SIZE; i++)
+      ULONG_PTR MemoryAreaLength = (ULONG_PTR)MemoryArea->EndingAddress -
+                                   (ULONG_PTR)MemoryArea->StartingAddress;
+
+      /* FiN TODO: Optimize loop counter! */
+      for (i = 0; i < PAGE_ROUND_UP(MemoryAreaLength) / PAGE_SIZE; i++)
       {
          PMM_PAGEOP PageOp;
 
@@ -712,7 +725,7 @@
          }
 
          PageOp = MmCheckForPageOp(MemoryArea, Process->UniqueProcessId,
-                                   (char*)MemoryArea->BaseAddress + (i * PAGE_SIZE),
+                                   (PVOID)((ULONG_PTR)MemoryArea->StartingAddress + (i * PAGE_SIZE)),
                                    NULL, 0);
          if (PageOp != NULL)
          {
@@ -745,8 +758,7 @@
 
    /* Actually free the memory area. */
    MmFreeMemoryArea(&Process->AddressSpace,
-                    MemoryArea->BaseAddress,
-                    0,
+                    MemoryArea,
                     MmFreeVirtualMemoryPage,
                     (PVOID)Process);
 }
@@ -814,7 +826,7 @@
    {
       case MEM_RELEASE:
          /* We can only free a memory area in one step. */
-         if (MemoryArea->BaseAddress != BaseAddress ||
+         if (MemoryArea->StartingAddress != BaseAddress ||
              MemoryArea->Type != MEMORY_AREA_VIRTUAL_MEMORY)
          {
             MmUnlockAddressSpace(AddressSpace);
@@ -829,7 +841,7 @@
       case MEM_DECOMMIT:
          Status =
             MmAlterRegion(AddressSpace,
-                          MemoryArea->BaseAddress,
+                          MemoryArea->StartingAddress,
                           &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                           BaseAddress,
                           RegionSize,
@@ -856,11 +868,11 @@
    PMM_REGION Region;
    NTSTATUS Status;
 
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                          BaseAddress, NULL);
    *OldProtect = Region->Protect;
-   Status = MmAlterRegion(AddressSpace, MemoryArea->BaseAddress,
+   Status = MmAlterRegion(AddressSpace, MemoryArea->StartingAddress,
                           &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                           BaseAddress, Length, Region->Type, Protect,
                           MmModifyAttributes);
@@ -878,11 +890,11 @@
 
    Info->BaseAddress = (PVOID)PAGE_ROUND_DOWN(Address);
 
-   Region = MmFindRegion(MemoryArea->BaseAddress,
+   Region = MmFindRegion(MemoryArea->StartingAddress,
                          &MemoryArea->Data.VirtualMemoryData.RegionListHead,
                          Address, &RegionBase);
    Info->BaseAddress = RegionBase;
-   Info->AllocationBase = MemoryArea->BaseAddress;
+   Info->AllocationBase = MemoryArea->StartingAddress;
    Info->AllocationProtect = MemoryArea->Attributes;
    Info->RegionSize = (char*)RegionBase + Region->Length - (char*)Info->BaseAddress;
    Info->State = Region->Type;

Modified: trunk/reactos/ntoskrnl/mm/aspace.c
--- trunk/reactos/ntoskrnl/mm/aspace.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/mm/aspace.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -68,7 +68,7 @@
 MmInitializeAddressSpace(PEPROCESS Process,
                          PMADDRESS_SPACE AddressSpace)
 {
-   InitializeListHead(&AddressSpace->MAreaListHead);
+   AddressSpace->MemoryAreaRoot = NULL;
    ExInitializeFastMutex(&AddressSpace->Lock);
    if (Process != NULL)
    {

Modified: trunk/reactos/ntoskrnl/mm/cont.c
--- trunk/reactos/ntoskrnl/mm/cont.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/mm/cont.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -1,4 +1,4 @@
-/* $Id: cont.c,v 1.35 2004/10/22 20:38:22 ekohl Exp $
+/* $Id$
  * 
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -42,7 +42,7 @@
 {
    PMEMORY_AREA MArea;
    NTSTATUS Status;
-   PVOID BaseAddress = 0;
+   PVOID BaseAddress = NULL;
    PFN_TYPE PBase;
    ULONG Attributes;
    ULONG i;
@@ -83,8 +83,7 @@
    {
       MmLockAddressSpace(MmGetKernelAddressSpace());
       MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                       BaseAddress,
-                       0,
+                       MArea,
                        NULL,
                        NULL);
       MmUnlockAddressSpace(MmGetKernelAddressSpace());
@@ -174,11 +173,10 @@
 MmFreeContiguousMemory(IN PVOID BaseAddress)
 {
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                    BaseAddress,
-                    0,
-                    MmFreeContinuousPage,
-                    NULL);
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         BaseAddress,
+                         MmFreeContinuousPage,
+                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
 
@@ -260,11 +258,10 @@
                                    IN MEMORY_CACHING_TYPE CacheType)
 {
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                    BaseAddress,
-                    NumberOfBytes,
-                    MmFreeContinuousPage,
-                    NULL);
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         BaseAddress,
+                         MmFreeContinuousPage,
+                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
 

Modified: trunk/reactos/ntoskrnl/mm/drvlck.c
--- trunk/reactos/ntoskrnl/mm/drvlck.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/mm/drvlck.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -1,4 +1,4 @@
-/* $Id: drvlck.c,v 1.6 2004/08/15 16:39:06 chorns Exp $
+/* $Id$
  *
  * COPYRIGHT:       See COPYING in the top level directory
  * PROJECT:         ReactOS kernel
@@ -64,7 +64,7 @@
 MmLockPagableDataSection(IN PVOID AddressWithinSection)
 {
    PVOID Handle;
-   Handle = MmOpenMemoryAreaByAddress(NULL,AddressWithinSection);
+   Handle = MmOpenMemoryAreaByAddress(NULL, AddressWithinSection);
    MmLockPagableSectionByHandle(Handle);
    return(Handle);
 }

Modified: trunk/reactos/ntoskrnl/mm/iospace.c
--- trunk/reactos/ntoskrnl/mm/iospace.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/mm/iospace.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -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: iospace.c,v 1.30 2004/08/15 16:39:07 chorns Exp $
+/* $Id$
  *
  * PROJECT:         ReactOS kernel
  * FILE:            ntoskrnl/mm/iospace.c
@@ -127,7 +127,7 @@
          KEBUGCHECK(0);
       }
    }
-   return ((PVOID)((char*)Result + Offset));
+   return (PVOID)((ULONG_PTR)Result + Offset);
 }
 
 
@@ -160,16 +160,17 @@
                 IN ULONG NumberOfBytes)
 {
    ULONG Offset;
-   Offset = (ULONG_PTR)BaseAddress % PAGE_SIZE;
-   BaseAddress = (PVOID)((PUCHAR)BaseAddress - Offset);
+   PVOID Address = BaseAddress;
+
+   Offset = (ULONG_PTR)Address % PAGE_SIZE;
+   Address -= Offset;
    NumberOfBytes += Offset;
 
    MmLockAddressSpace(MmGetKernelAddressSpace());
-   MmFreeMemoryArea(MmGetKernelAddressSpace(),
-                    BaseAddress,
-                    NumberOfBytes,
-                    NULL,
-                    NULL);
+   MmFreeMemoryAreaByPtr(MmGetKernelAddressSpace(),
+                         Address,
+                         NULL,
+                         NULL);
    MmUnlockAddressSpace(MmGetKernelAddressSpace());
 }
 

Modified: trunk/reactos/ntoskrnl/mm/marea.c
--- trunk/reactos/ntoskrnl/mm/marea.c	2005-01-02 17:47:07 UTC (rev 12727)
+++ trunk/reactos/ntoskrnl/mm/marea.c	2005-01-02 17:55:06 UTC (rev 12728)
@@ -35,331 +35,590 @@
 
 #define TAG_MAREA   TAG('M', 'A', 'R', 'E')
 
+/* #define VALIDATE_MEMORY_AREAS */
+
 /* FUNCTIONS *****************************************************************/
 
-VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead)
+/**
+ * @name MmIterateFirstNode
+ *
+ * @param Node
+ *        Head node of the MEMORY_AREA tree.
+ *
+ * @return The leftmost MEMORY_AREA node (ie. the one with lowest
+ *         address)
+ */
+
+static PMEMORY_AREA MmIterateFirstNode(PMEMORY_AREA Node)
 {
-   PLIST_ENTRY current_entry;
-   MEMORY_AREA* current;
+   while (Node->LeftChild != NULL)
+      Node = Node->LeftChild;
 
+   return Node;
+}
+
+/**
+ * @name MmIterateNextNode
+ *
+ * @param Node
+ *        Current node in the tree.
+ *
+ * @return Next node in the tree (sorted by address).
+ */
+
+static PMEMORY_AREA MmIterateNextNode(PMEMORY_AREA Node)
+{
+   if (Node->RightChild != NULL)
+   {
+      Node = Node->RightChild;
+      while (Node->LeftChild != NULL)
+         Node = Node->LeftChild;
+   }
+   else
+   {
+      PMEMORY_AREA TempNode = NULL;
+ 
+      do
+      {
+         /* Check if we're at the end of tree. */
+         if (Node->Parent == NULL)
+            return NULL;
+ 
+         TempNode = Node;
+         Node = Node->Parent;
+      }
+      while (TempNode == Node->RightChild);
+   }
+   return Node;
+}
+
+/**
+ * @name MmIterateFirstNode
+ *
+ * @param Node
+ *        Head node of the MEMORY_AREA tree.
+ *
+ * @return The rightmost MEMORY_AREA node (ie. the one with highest
+ *         address)
+ */
+
+static PMEMORY_AREA MmIterateLastNode(PMEMORY_AREA Node)
+{
+   while (Node->RightChild != NULL)
+      Node = Node->RightChild;
+
+   return Node;
+}
+
+/**
+ * @name MmIterateNextNode
+ *
+ * @param Node
+ *        Current node in the tree.
+ *
+ * @return Previous node in the tree (sorted by address).
+ */
+
+static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node)
+{
+   if (Node->LeftChild != NULL)
+   {
+      Node = Node->LeftChild;
+      while (Node->RightChild != NULL)
+         Node = Node->RightChild;
+   }
+   else
+   {
+      PMEMORY_AREA TempNode = NULL;
+ 
+      do
+      {
+         /* Check if we're at the end of tree. */
+         if (Node->Parent == NULL)
+            return NULL;
+ 
+         TempNode = Node;
+         Node = Node->Parent;
+      }
+      while (TempNode == Node->LeftChild);
+   }
+   return Node;
+}
+
+#ifdef VALIDATE_MEMORY_AREAS
+static VOID MmVerifyMemoryAreas(PMADDRESS_SPACE AddressSpace)
+{
+   PMEMORY_AREA Node;
+
+   ASSERT(AddressSpace != NULL);
+   
+   /* Special case for empty tree. */
+   if (AddressSpace->MemoryAreaRoot == NULL)
+      return;
+
+   /* Traverse the tree from left to right. */
+   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+        Node != NULL;
+        Node = MmIterateNextNode(Node))
+   {
+      /* FiN: The starting address can be NULL if someone explicitely asks
+       * for NULL address. */
+      ASSERT(Node->StartingAddress >= AddressSpace->LowestAddress ||
+             Node->StartingAddress == NULL);
+      ASSERT(Node->EndingAddress >= Node->StartingAddress);
+   }
+}
+#else
+#define MmVerifyMemoryAreas(x) 
+#endif
+
+VOID STDCALL
+MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace)
+{
+   PMEMORY_AREA Node;
+
    DbgPrint("MmDumpMemoryAreas()\n");
+   
+   /* Special case for empty tree. */
+   if (AddressSpace->MemoryAreaRoot == NULL)
+      return;
 
-   current_entry = ListHead->Flink;
-   while (current_entry!=ListHead)
+   /* Traverse the tree from left to right. */
+   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+        Node != NULL;
+        Node = MmIterateNextNode(Node))
    {
-      current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-      DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
-               current->BaseAddress,current->Length,
-               (char*)current->BaseAddress+current->Length,current->Attributes,
-               current->Entry.Flink);
-      current_entry = current_entry->Flink;
+      DbgPrint("Start %x End %x Attributes %x\n",
+               Node->StartingAddress, Node->EndingAddress,
+               Node->Attributes);
    }
+
    DbgPrint("Finished MmDumpMemoryAreas()\n");
 }
 
-MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace,
-                                       PVOID Address)
+PMEMORY_AREA STDCALL
+MmOpenMemoryAreaByAddress(
+   PMADDRESS_SPACE AddressSpace,
+   PVOID Address)
 {
-   PLIST_ENTRY current_entry;
-   MEMORY_AREA* current;
-   PLIST_ENTRY previous_entry;
+   PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot;
 
    DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
-          AddressSpace, Address);
+           AddressSpace, Address);
 
-   previous_entry = &AddressSpace->MAreaListHead;
-   current_entry = AddressSpace->MAreaListHead.Flink;
-   while (current_entry != &AddressSpace->MAreaListHead)
+   if (!(KdDebugState & KD_DEBUG_SCREEN))
+      MmVerifyMemoryAreas(AddressSpace);
+
+   while (Node != NULL)
    {
-      current = CONTAINING_RECORD(current_entry,
-                                  MEMORY_AREA,
-                                  Entry);
-      ASSERT(current_entry->Blink->Flink == current_entry);
-      ASSERT(current_entry->Flink->Blink == current_entry);
-      ASSERT(previous_entry->Flink == current_entry);
-      if (current->BaseAddress <= Address &&
-            (PVOID)((char*)current->BaseAddress + current->Length) > Address)
+      if (Address < Node->StartingAddress)
+         Node = Node->LeftChild;
+      else if (Address >= Node->EndingAddress)
+         Node = Node->RightChild;
+      else
       {
-         DPRINT("%s() = %x\n",__FUNCTION__,current);
-         return(current);
+         DPRINT("MmOpenMemoryAreaByAddress(%x): %x [%x - %x]\n",
+                Address, Node, Node->StartingAddress, Node->EndingAddress);
+         return Node;
       }
-      if (current->BaseAddress > Address)
-      {
-         DPRINT("%s() = NULL\n",__FUNCTION__);
-         return(NULL);
-      }
-      previous_entry = current_entry;
-      current_entry = current_entry->Flink;
    }
-   DPRINT("%s() = NULL\n",__FUNCTION__);
-   return(NULL);
+
+   DPRINT("MmOpenMemoryAreaByAddress(%x): 0\n", Address);
+   return NULL;
 }
 
-MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
-                                      PVOID Address,
-                                      ULONG Length)
+PMEMORY_AREA STDCALL
+MmOpenMemoryAreaByRegion(
+   PMADDRESS_SPACE AddressSpace,
+   PVOID Address,
+   ULONG_PTR Length)
 {
-   PLIST_ENTRY current_entry;
-   MEMORY_AREA* current;
-   ULONG Extent;
+   PMEMORY_AREA Node;
+   PVOID Extent = (PVOID)((ULONG_PTR)Address + Length);
 
-   DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
-          AddressSpace, Address, Length);
+   MmVerifyMemoryAreas(AddressSpace);
 
-   current_entry = AddressSpace->MAreaListHead.Flink;
-   while (current_entry != &AddressSpace->MAreaListHead)
+   /* Special case for empty tree. */
+   if (AddressSpace->MemoryAreaRoot == NULL)
+      return NULL;
+
+   /* Traverse the tree from left to right. */
+   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+        Node != NULL;
+        Node = MmIterateNextNode(Node))
    {
-      current = CONTAINING_RECORD(current_entry,
-                                  MEMORY_AREA,
-                                  Entry);
-      DPRINT("current->BaseAddress %x current->Length %x\n",
-             current->BaseAddress,current->Length);
-      if (current->BaseAddress >= Address &&
-            current->BaseAddress < (PVOID)((char*)Address+Length))
+      if (Node->StartingAddress >= Address &&
+          Node->StartingAddress < Extent)
       {
-         DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
-                current);
-         return(current);
+         DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n",
+                Address, Address + Length, Node->StartingAddress,
+                Node->EndingAddress);
+         return Node;
       }
-      Extent = (ULONG)current->BaseAddress + current->Length;
-      if (Extent > (ULONG)Address &&
-            Extent < (ULONG)((char*)Address+Length))
+      if (Node->EndingAddress > Address &&
+          Node->EndingAddress < Extent)
       {
-         DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
-                current);
-         return(current);
+         DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n",
+                Address, Address + Length, Node->StartingAddress,
+                Node->EndingAddress);
+         return Node;
       }
-      if (current->BaseAddress <= Address &&
-            Extent >= (ULONG)((char*)Address+Length))
+      if (Node->StartingAddress <= Address &&
+          Node->EndingAddress >= Extent)
       {
-         DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
-                current);
-         return(current);
+         DPRINT("MmOpenMemoryAreaByRegion(%x - %x): %x - %x\n",
+                Address, Address + Length, Node->StartingAddress,
+                Node->EndingAddress);
+         return Node;
       }
-      if (current->BaseAddress >= (PVOID)((char*)Address+Length))
+      if (Node->StartingAddress >= Extent)
       {
-         DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
-         return(NULL);
+         DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n");
+         return NULL;
       }
-      current_entry = current_entry->Flink;
    }
-   DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
-   return(NULL);
+
+   return NULL;
 }
 
-static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace,
-                               MEMORY_AREA* marea)
+/*
+ * @name MmCompressHelper
+ *
+ * This is helper of MmRebalanceTree. Performs a compression transformation
+ * count times, starting at root. 
+ */
+
+static VOID
+MmCompressHelper(
+   PMADDRESS_SPACE AddressSpace,
+   ULONG Count) 
 {
-   PLIST_ENTRY ListHead;
-   PLIST_ENTRY current_entry;
-   PLIST_ENTRY inserted_entry = &marea->Entry;
-   MEMORY_AREA* current;
-   MEMORY_AREA* next;
+   PMEMORY_AREA Root = NULL;
+   PMEMORY_AREA Red = AddressSpace->MemoryAreaRoot;
+   PMEMORY_AREA Black = Red->LeftChild;
 
-   DPRINT("MmInsertMemoryArea(marea %x)\n", marea);
-   DPRINT("marea->BaseAddress %x\n", marea->BaseAddress);
-   DPRINT("marea->Length %x\n", marea->Length);
+   while (Count--)
+   {
+      if (Root)
+         Root->LeftChild = Black;
+      else
+         AddressSpace->MemoryAreaRoot = Black;
+      Black->Parent = Root;
+      Red->LeftChild = Black->RightChild;
+      if (Black->RightChild)
+         Black->RightChild->Parent = Red;
+      Black->RightChild = Red;
+      Red->Parent = Black;
+      Root = Black;
 
-   ListHead = &AddressSpace->MAreaListHead;
-
-   current_entry = ListHead->Flink;
-   if (IsListEmpty(ListHead))
-   {
-      InsertHeadList(ListHead,&marea->Entry);
-      return;
-   }
-   current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-   if (current->BaseAddress > marea->BaseAddress)
-   {
-      InsertHeadList(ListHead,&marea->Entry);
-      return;
-   }
-   while (current_entry->Flink!=ListHead)
-   {
-      current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
-      next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
-      if (current->BaseAddress < marea->BaseAddress &&
-            current->Entry.Flink==ListHead)
+      if (Count)
       {
-         current_entry->Flink = inserted_entry;
-         inserted_entry->Flink=ListHead;
-         inserted_entry->Blink=current_entry;
-         ListHead->Blink = inserted_entry;
-         return;
+         Red = Root->LeftChild;
+         Black = Red->LeftChild;
       }
-      if (current->BaseAddress < marea->BaseAddress &&
[truncated at 1000 lines; 1533 more skipped]