Sync with trunk (48237)
[reactos.git] / ntoskrnl / mm / marea.c
index 8776349..0466de0 100644 (file)
@@ -45,9 +45,8 @@
 #define NDEBUG
 #include <debug.h>
 
-#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, MmInitMemoryAreas)
-#endif
+MEMORY_AREA MiStaticMemoryAreas[MI_STATIC_MEMORY_AREAS];
+ULONG MiStaticMemoryAreaCount;
 
 /* #define VALIDATE_MEMORY_AREAS */
 
@@ -160,18 +159,18 @@ static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node)
 }
 
 #ifdef VALIDATE_MEMORY_AREAS
-static VOID MmVerifyMemoryAreas(PMM_AVL_TABLE AddressSpace)
+static VOID MmVerifyMemoryAreas(PMMSUPPORT AddressSpace)
 {
    PMEMORY_AREA Node;
 
    ASSERT(AddressSpace != NULL);
 
    /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
       return;
 
    /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode(AddressSpace->BalancedRoot.u1.Parent);
+   for (Node = MmIterateFirstNode(AddressSpace->WorkingSetExpansionLinks.Flink);
         Node != NULL;
         Node = MmIterateNextNode(Node))
    {
@@ -185,19 +184,19 @@ static VOID MmVerifyMemoryAreas(PMM_AVL_TABLE AddressSpace)
 #define MmVerifyMemoryAreas(x)
 #endif
 
-VOID STDCALL
-MmDumpMemoryAreas(PMM_AVL_TABLE AddressSpace)
+VOID NTAPI
+MmDumpMemoryAreas(PMMSUPPORT AddressSpace)
 {
    PMEMORY_AREA Node;
 
    DbgPrint("MmDumpMemoryAreas()\n");
 
    /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
       return;
 
    /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent);
+   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
         Node != NULL;
         Node = MmIterateNextNode(Node))
    {
@@ -209,12 +208,12 @@ MmDumpMemoryAreas(PMM_AVL_TABLE AddressSpace)
    DbgPrint("Finished MmDumpMemoryAreas()\n");
 }
 
-PMEMORY_AREA STDCALL
+PMEMORY_AREA NTAPI
 MmLocateMemoryAreaByAddress(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address)
 {
-   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
 
    DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %p, Address %p)\n",
            AddressSpace, Address);
@@ -239,9 +238,9 @@ MmLocateMemoryAreaByAddress(
    return NULL;
 }
 
-PMEMORY_AREA STDCALL
+PMEMORY_AREA NTAPI
 MmLocateMemoryAreaByRegion(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address,
    ULONG_PTR Length)
 {
@@ -251,11 +250,11 @@ MmLocateMemoryAreaByRegion(
    MmVerifyMemoryAreas(AddressSpace);
 
    /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
       return NULL;
 
    /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent);
+   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
         Node != NULL;
         Node = MmIterateNextNode(Node))
    {
@@ -302,11 +301,11 @@ MmLocateMemoryAreaByRegion(
 
 static VOID
 MmCompressHelper(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG Count)
 {
    PMEMORY_AREA Root = NULL;
-   PMEMORY_AREA Red = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   PMEMORY_AREA Red = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    PMEMORY_AREA Black = Red->LeftChild;
 
    while (Count--)
@@ -314,7 +313,7 @@ MmCompressHelper(
       if (Root)
          Root->LeftChild = Black;
       else
-         AddressSpace->BalancedRoot.u1.Parent = (PVOID)Black;
+         AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)Black;
       Black->Parent = Root;
       Red->LeftChild = Black->RightChild;
       if (Black->RightChild)
@@ -341,7 +340,7 @@ MmCompressHelper(
 
 static VOID
 MmRebalanceTree(
-   PMM_AVL_TABLE AddressSpace)
+   PMMSUPPORT AddressSpace)
 {
    PMEMORY_AREA PreviousNode;
    PMEMORY_AREA CurrentNode;
@@ -354,7 +353,7 @@ MmRebalanceTree(
    /* Transform the tree into Vine. */
 
    PreviousNode = NULL;
-   CurrentNode = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   CurrentNode = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    while (CurrentNode != NULL)
    {
       if (CurrentNode->RightChild == NULL)
@@ -379,7 +378,7 @@ MmRebalanceTree(
          if (PreviousNode != NULL)
             PreviousNode->LeftChild = TempNode;
          else
-            AddressSpace->BalancedRoot.u1.Parent = (PVOID)TempNode;
+            AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)TempNode;
          TempNode->Parent = PreviousNode;
       }
    }
@@ -410,7 +409,7 @@ MmRebalanceTree(
 
 static VOID
 MmInsertMemoryArea(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PMEMORY_AREA marea)
 {
    PMEMORY_AREA Node;
@@ -419,14 +418,14 @@ MmInsertMemoryArea(
 
    MmVerifyMemoryAreas(AddressSpace);
 
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
-      AddressSpace->BalancedRoot.u1.Parent = (PVOID)marea;
+      AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)marea;
       marea->LeftChild = marea->RightChild = marea->Parent = NULL;
       return;
    }
 
-   Node = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    do
    {
       DPRINT("marea->EndingAddress: %p Node->StartingAddress: %p\n",
@@ -466,7 +465,7 @@ MmInsertMemoryArea(
 
 static PVOID
 MmFindGapBottomUp(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity)
 {
@@ -486,7 +485,7 @@ MmFindGapBottomUp(
    AlignedAddress = MM_ROUND_UP(LowestAddress, Granularity);
 
    /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
       if ((ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
       {
@@ -498,7 +497,7 @@ MmFindGapBottomUp(
    }
 
    /* Go to the node with lowest address in the tree. */
-   FirstNode = Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent);
+   FirstNode = Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
 
    /* Traverse the tree from left to right. */
    PreviousNode = Node;
@@ -544,7 +543,7 @@ MmFindGapBottomUp(
 
 static PVOID
 MmFindGapTopDown(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity)
 {
@@ -567,7 +566,7 @@ MmFindGapTopDown(
       return NULL;
 
    /* Special case for empty tree. */
-   if (AddressSpace->BalancedRoot.u1.Parent == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
       if (AlignedAddress >= LowestAddress)
       {
@@ -579,7 +578,7 @@ MmFindGapTopDown(
    }
 
    /* Go to the node with highest address in the tree. */
-   Node = MmIterateLastNode((PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent);
+   Node = MmIterateLastNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
 
    /* Check if there is enough space after the last memory area. */
    if (Node->EndingAddress <= AlignedAddress)
@@ -628,9 +627,9 @@ MmFindGapTopDown(
 }
 
 
-PVOID STDCALL
+PVOID NTAPI
 MmFindGap(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity,
    BOOLEAN TopDown)
@@ -641,12 +640,12 @@ MmFindGap(
    return MmFindGapBottomUp(AddressSpace, Length, Granularity);
 }
 
-ULONG_PTR STDCALL
+ULONG_PTR NTAPI
 MmFindGapAtAddress(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address)
 {
-   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->BalancedRoot.u1.Parent;
+   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    PMEMORY_AREA RightNeighbour = NULL;
    PVOID LowestAddress  = MmGetAddressSpaceOwner(AddressSpace) ? MM_LOWEST_USER_ADDRESS : MmSystemRangeStart;
    PVOID HighestAddress = MmGetAddressSpaceOwner(AddressSpace) ?
@@ -703,21 +702,6 @@ MmFindGapAtAddress(
    }
 }
 
-/**
- * @name MmInitMemoryAreas
- *
- * Initialize the memory area list implementation.
- */
-
-NTSTATUS
-INIT_FUNCTION
-NTAPI
-MmInitMemoryAreas(VOID)
-{
-   DPRINT("MmInitMemoryAreas()\n");
-   return(STATUS_SUCCESS);
-}
-
 
 /**
  * @name MmFreeMemoryArea
@@ -738,9 +722,9 @@ MmInitMemoryAreas(VOID)
  * @remarks Lock the address space before calling this function.
  */
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 MmFreeMemoryArea(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PMEMORY_AREA MemoryArea,
    PMM_FREE_PAGE_FUNC FreePage,
    PVOID FreePageContext)
@@ -748,51 +732,55 @@ MmFreeMemoryArea(
    PMEMORY_AREA *ParentReplace;
    ULONG_PTR Address;
    PVOID EndAddress;
-   PEPROCESS CurrentProcess = PsGetCurrentProcess();
-   PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
-    
-   if (Process != NULL &&
-       Process != CurrentProcess)
-   {
-      KeAttachProcess(&Process->Pcb);
-   }
-
-   EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE);
-   for (Address = (ULONG_PTR)MemoryArea->StartingAddress;
-        Address < (ULONG_PTR)EndAddress;
-        Address += PAGE_SIZE)
-   {
-      if (MemoryArea->Type == MEMORY_AREA_IO_MAPPING)
-      {
-         MmRawDeleteVirtualMapping((PVOID)Address);
-      }
-      else
-      {
-         BOOLEAN Dirty = FALSE;
-         SWAPENTRY SwapEntry = 0;
-         PFN_TYPE Page = 0;
-
-         if (MmIsPageSwapEntry(Process, (PVOID)Address))
-         {
-            MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry);
-         }
-         else
-         {
-            MmDeleteVirtualMapping(Process, (PVOID)Address, FALSE, &Dirty, &Page);
-         }
-         if (FreePage != NULL)
-         {
-            FreePage(FreePageContext, MemoryArea, (PVOID)Address,
-                     Page, SwapEntry, (BOOLEAN)Dirty);
-         }
-      }
-   }
-
-   if (Process != NULL &&
-       Process != CurrentProcess)
+   
+   if (MemoryArea->Type != MEMORY_AREA_OWNED_BY_ARM3)
    {
-      KeDetachProcess();
-   }
+       PEPROCESS CurrentProcess = PsGetCurrentProcess();
+       PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+        
+       if (Process != NULL &&
+           Process != CurrentProcess)
+       {
+          KeAttachProcess(&Process->Pcb);
+       }
+
+       EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE);
+       for (Address = (ULONG_PTR)MemoryArea->StartingAddress;
+            Address < (ULONG_PTR)EndAddress;
+            Address += PAGE_SIZE)
+       {
+          if (MemoryArea->Type == MEMORY_AREA_IO_MAPPING)
+          {
+             MmRawDeleteVirtualMapping((PVOID)Address);
+          }
+          else
+          {
+             BOOLEAN Dirty = FALSE;
+             SWAPENTRY SwapEntry = 0;
+             PFN_NUMBER Page = 0;
+
+             if (MmIsPageSwapEntry(Process, (PVOID)Address))
+             {
+                MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry);
+             }
+             else
+             {
+                MmDeleteVirtualMapping(Process, (PVOID)Address, FALSE, &Dirty, &Page);
+             }
+             if (FreePage != NULL)
+             {
+                FreePage(FreePageContext, MemoryArea, (PVOID)Address,
+                         Page, SwapEntry, (BOOLEAN)Dirty);
+             }
+          }
+       }
+
+       if (Process != NULL &&
+           Process != CurrentProcess)
+       {
+          KeDetachProcess();
+       }
+    }
 
    /* Remove the tree item. */
    {
@@ -804,7 +792,7 @@ MmFreeMemoryArea(
             ParentReplace = &MemoryArea->Parent->RightChild;
       }
       else
-         ParentReplace = (PMEMORY_AREA*)&AddressSpace->BalancedRoot.u1.Parent;
+         ParentReplace = (PMEMORY_AREA*)&AddressSpace->WorkingSetExpansionLinks.Flink;
 
       if (MemoryArea->RightChild == NULL)
       {
@@ -880,9 +868,9 @@ MmFreeMemoryArea(
  * @remarks Lock the address space before calling this function.
  */
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 MmFreeMemoryAreaByPtr(
-   PMM_AVL_TABLE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID BaseAddress,
    PMM_FREE_PAGE_FUNC FreePage,
    PVOID FreePageContext)
@@ -899,7 +887,7 @@ MmFreeMemoryAreaByPtr(
                                             BaseAddress);
    if (MemoryArea == NULL)
    {
-      ASSERT(FALSE);
+      KeBugCheck(MEMORY_MANAGEMENT);
       return(STATUS_UNSUCCESSFUL);
    }
 
@@ -932,8 +920,8 @@ MmFreeMemoryAreaByPtr(
  * @remarks Lock the address space before calling this function.
  */
 
-NTSTATUS STDCALL
-MmCreateMemoryArea(PMM_AVL_TABLE AddressSpace,
+NTSTATUS NTAPI
+MmCreateMemoryArea(PMMSUPPORT AddressSpace,
                    ULONG Type,
                    PVOID *BaseAddress,
                    ULONG_PTR Length,
@@ -1001,9 +989,31 @@ MmCreateMemoryArea(PMM_AVL_TABLE AddressSpace,
          return STATUS_CONFLICTING_ADDRESSES;
       }
    }
+    
+    //
+    // Is this a static memory area?
+    //
+    if (Type & MEMORY_AREA_STATIC)
+    {
+        //
+        // Use the static array instead of the pool
+        //
+        ASSERT(MiStaticMemoryAreaCount < MI_STATIC_MEMORY_AREAS);
+        MemoryArea = &MiStaticMemoryAreas[MiStaticMemoryAreaCount++];
+        Type &= ~MEMORY_AREA_STATIC;
+    }
+    else
+    {
+        //
+        // Allocate the memory area from nonpaged pool
+        //
+        MemoryArea = ExAllocatePoolWithTag(NonPagedPool,
+                                           sizeof(MEMORY_AREA),
+                                           TAG_MAREA);
+    }
+
+    if (!MemoryArea) return STATUS_NO_MEMORY;
 
-   MemoryArea = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
-                                      TAG_MAREA);
    RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
    MemoryArea->Type = Type;
    MemoryArea->StartingAddress = *BaseAddress;
@@ -1033,13 +1043,13 @@ MmMapMemoryArea(PVOID BaseAddress,
 
    for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
    {
-      PFN_TYPE Page;
+      PFN_NUMBER Page;
 
       Status = MmRequestPageMemoryConsumer(Consumer, TRUE, &Page);
       if (!NT_SUCCESS(Status))
       {
          DPRINT1("Unable to allocate page\n");
-         ASSERT(FALSE);
+         KeBugCheck(MEMORY_MANAGEMENT);
       }
       Status = MmCreateVirtualMapping (NULL,
                                        (PVOID)((ULONG_PTR)BaseAddress + (i * PAGE_SIZE)),
@@ -1049,15 +1059,15 @@ MmMapMemoryArea(PVOID BaseAddress,
       if (!NT_SUCCESS(Status))
       {
          DPRINT1("Unable to create virtual mapping\n");
-         ASSERT(FALSE);
+         KeBugCheck(MEMORY_MANAGEMENT);
       }
    }
 }
 
 
-VOID STDCALL
+VOID NTAPI
 MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process,
-                                 PMM_AVL_TABLE AddressSpace,
+                                 PMMSUPPORT AddressSpace,
                                  PVOID BaseAddress)
 {
    PMEMORY_AREA MemoryArea;