- wdm.h: Define ALLOC_PRAGMA and ALLOC_DATA_PRAGMA for MSVC.
[reactos.git] / reactos / ntoskrnl / mm / marea.c
index cad4fe8..7ac02d8 100644 (file)
@@ -1,5 +1,4 @@
-/* $Id$
- *
+/*
  * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
  *
  * This program is free software; you can redistribute it and/or
@@ -29,7 +28,7 @@
  *                  Eric Kohl
  *                  Ge van Geldorp
  *                  Royce Mitchell III
- *                  Aleksey Bragin 
+ *                  Aleksey Bragin
  *                  Jason Filby
  *                  Thomas Weidenmueller
  *                  Gunnar Andre' Dalsnes
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#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 */
 
@@ -161,25 +159,24 @@ static PMEMORY_AREA MmIteratePrevNode(PMEMORY_AREA Node)
 }
 
 #ifdef VALIDATE_MEMORY_AREAS
-static VOID MmVerifyMemoryAreas(PMADDRESS_SPACE AddressSpace)
+static VOID MmVerifyMemoryAreas(PMMSUPPORT AddressSpace)
 {
    PMEMORY_AREA Node;
 
    ASSERT(AddressSpace != NULL);
 
    /* Special case for empty tree. */
-   if (AddressSpace->MemoryAreaRoot == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
       return;
 
    /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+   for (Node = MmIterateFirstNode(AddressSpace->WorkingSetExpansionLinks.Flink);
         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->StartingAddress == NULL);
       ASSERT(Node->EndingAddress >= Node->StartingAddress);
    }
 }
@@ -187,19 +184,19 @@ static VOID MmVerifyMemoryAreas(PMADDRESS_SPACE AddressSpace)
 #define MmVerifyMemoryAreas(x)
 #endif
 
-VOID STDCALL
-MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace)
+VOID NTAPI
+MmDumpMemoryAreas(PMMSUPPORT AddressSpace)
 {
    PMEMORY_AREA Node;
 
    DbgPrint("MmDumpMemoryAreas()\n");
 
    /* Special case for empty tree. */
-   if (AddressSpace->MemoryAreaRoot == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
       return;
 
    /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
         Node != NULL;
         Node = MmIterateNextNode(Node))
    {
@@ -211,12 +208,12 @@ MmDumpMemoryAreas(PMADDRESS_SPACE AddressSpace)
    DbgPrint("Finished MmDumpMemoryAreas()\n");
 }
 
-PMEMORY_AREA STDCALL
+PMEMORY_AREA NTAPI
 MmLocateMemoryAreaByAddress(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address)
 {
-   PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot;
+   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
 
    DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %p, Address %p)\n",
            AddressSpace, Address);
@@ -241,9 +238,9 @@ MmLocateMemoryAreaByAddress(
    return NULL;
 }
 
-PMEMORY_AREA STDCALL
+PMEMORY_AREA NTAPI
 MmLocateMemoryAreaByRegion(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address,
    ULONG_PTR Length)
 {
@@ -253,11 +250,11 @@ MmLocateMemoryAreaByRegion(
    MmVerifyMemoryAreas(AddressSpace);
 
    /* Special case for empty tree. */
-   if (AddressSpace->MemoryAreaRoot == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
       return NULL;
 
    /* Traverse the tree from left to right. */
-   for (Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+   for (Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
         Node != NULL;
         Node = MmIterateNextNode(Node))
    {
@@ -304,11 +301,11 @@ MmLocateMemoryAreaByRegion(
 
 static VOID
 MmCompressHelper(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG Count)
 {
    PMEMORY_AREA Root = NULL;
-   PMEMORY_AREA Red = AddressSpace->MemoryAreaRoot;
+   PMEMORY_AREA Red = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    PMEMORY_AREA Black = Red->LeftChild;
 
    while (Count--)
@@ -316,7 +313,7 @@ MmCompressHelper(
       if (Root)
          Root->LeftChild = Black;
       else
-         AddressSpace->MemoryAreaRoot = Black;
+         AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)Black;
       Black->Parent = Root;
       Red->LeftChild = Black->RightChild;
       if (Black->RightChild)
@@ -343,7 +340,7 @@ MmCompressHelper(
 
 static VOID
 MmRebalanceTree(
-   PMADDRESS_SPACE AddressSpace)
+   PMMSUPPORT AddressSpace)
 {
    PMEMORY_AREA PreviousNode;
    PMEMORY_AREA CurrentNode;
@@ -356,7 +353,7 @@ MmRebalanceTree(
    /* Transform the tree into Vine. */
 
    PreviousNode = NULL;
-   CurrentNode = AddressSpace->MemoryAreaRoot;
+   CurrentNode = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    while (CurrentNode != NULL)
    {
       if (CurrentNode->RightChild == NULL)
@@ -381,7 +378,7 @@ MmRebalanceTree(
          if (PreviousNode != NULL)
             PreviousNode->LeftChild = TempNode;
          else
-            AddressSpace->MemoryAreaRoot = TempNode;
+            AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)TempNode;
          TempNode->Parent = PreviousNode;
       }
    }
@@ -412,7 +409,7 @@ MmRebalanceTree(
 
 static VOID
 MmInsertMemoryArea(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PMEMORY_AREA marea)
 {
    PMEMORY_AREA Node;
@@ -421,14 +418,14 @@ MmInsertMemoryArea(
 
    MmVerifyMemoryAreas(AddressSpace);
 
-   if (AddressSpace->MemoryAreaRoot == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
-      AddressSpace->MemoryAreaRoot = marea;
+      AddressSpace->WorkingSetExpansionLinks.Flink = (PVOID)marea;
       marea->LeftChild = marea->RightChild = marea->Parent = NULL;
       return;
    }
 
-   Node = AddressSpace->MemoryAreaRoot;
+   Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    do
    {
       DPRINT("marea->EndingAddress: %p Node->StartingAddress: %p\n",
@@ -468,11 +465,12 @@ MmInsertMemoryArea(
 
 static PVOID
 MmFindGapBottomUp(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity)
 {
-   PVOID HighestAddress = AddressSpace->LowestAddress < MmSystemRangeStart ?
+   PVOID LowestAddress  = MmGetAddressSpaceOwner(AddressSpace) ? MM_LOWEST_USER_ADDRESS : MmSystemRangeStart;
+   PVOID HighestAddress = MmGetAddressSpaceOwner(AddressSpace) ?
                           (PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
    PVOID AlignedAddress;
    PMEMORY_AREA Node;
@@ -482,12 +480,12 @@ MmFindGapBottomUp(
    MmVerifyMemoryAreas(AddressSpace);
 
    DPRINT("LowestAddress: %p HighestAddress: %p\n",
-          AddressSpace->LowestAddress, HighestAddress);
+          LowestAddress, HighestAddress);
 
-   AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
+   AlignedAddress = MM_ROUND_UP(LowestAddress, Granularity);
 
    /* Special case for empty tree. */
-   if (AddressSpace->MemoryAreaRoot == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
       if ((ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
       {
@@ -499,7 +497,7 @@ MmFindGapBottomUp(
    }
 
    /* Go to the node with lowest address in the tree. */
-   FirstNode = Node = MmIterateFirstNode(AddressSpace->MemoryAreaRoot);
+   FirstNode = Node = MmIterateFirstNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
 
    /* Traverse the tree from left to right. */
    PreviousNode = Node;
@@ -530,7 +528,7 @@ MmFindGapBottomUp(
    }
 
    /* Check if there is enough space before the first memory area. */
-   AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
+   AlignedAddress = MM_ROUND_UP(LowestAddress, Granularity);
    if (FirstNode->StartingAddress > AlignedAddress &&
        (ULONG_PTR)FirstNode->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
    {
@@ -545,11 +543,12 @@ MmFindGapBottomUp(
 
 static PVOID
 MmFindGapTopDown(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity)
 {
-   PVOID HighestAddress = AddressSpace->LowestAddress < MmSystemRangeStart ?
+   PVOID LowestAddress  = MmGetAddressSpaceOwner(AddressSpace) ? MM_LOWEST_USER_ADDRESS : MmSystemRangeStart;
+   PVOID HighestAddress = MmGetAddressSpaceOwner(AddressSpace) ?
                           (PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
    PVOID AlignedAddress;
    PMEMORY_AREA Node;
@@ -558,7 +557,7 @@ MmFindGapTopDown(
    MmVerifyMemoryAreas(AddressSpace);
 
    DPRINT("LowestAddress: %p HighestAddress: %p\n",
-          AddressSpace->LowestAddress, HighestAddress);
+          LowestAddress, HighestAddress);
 
    AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)HighestAddress - Length + 1, Granularity);
 
@@ -567,9 +566,9 @@ MmFindGapTopDown(
       return NULL;
 
    /* Special case for empty tree. */
-   if (AddressSpace->MemoryAreaRoot == NULL)
+   if (AddressSpace->WorkingSetExpansionLinks.Flink == NULL)
    {
-      if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress)
+      if (AlignedAddress >= LowestAddress)
       {
          DPRINT("MmFindGapTopDown: %p\n", AlignedAddress);
          return AlignedAddress;
@@ -579,7 +578,7 @@ MmFindGapTopDown(
    }
 
    /* Go to the node with highest address in the tree. */
-   Node = MmIterateLastNode(AddressSpace->MemoryAreaRoot);
+   Node = MmIterateLastNode((PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink);
 
    /* Check if there is enough space after the last memory area. */
    if (Node->EndingAddress <= AlignedAddress)
@@ -617,7 +616,7 @@ MmFindGapTopDown(
    if (AlignedAddress > PreviousNode->StartingAddress)
       return NULL;
 
-   if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress)
+   if (AlignedAddress >= LowestAddress)
    {
       DPRINT("MmFindGapTopDown: %p\n", AlignedAddress);
       return AlignedAddress;
@@ -628,9 +627,9 @@ MmFindGapTopDown(
 }
 
 
-PVOID STDCALL
+PVOID NTAPI
 MmFindGap(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    ULONG_PTR Length,
    ULONG_PTR Granularity,
    BOOLEAN TopDown)
@@ -641,21 +640,22 @@ MmFindGap(
    return MmFindGapBottomUp(AddressSpace, Length, Granularity);
 }
 
-ULONG_PTR STDCALL
+ULONG_PTR NTAPI
 MmFindGapAtAddress(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID Address)
 {
-   PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot;
+   PMEMORY_AREA Node = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
    PMEMORY_AREA RightNeighbour = NULL;
-   PVOID HighestAddress = AddressSpace->LowestAddress < MmSystemRangeStart ?
+   PVOID LowestAddress  = MmGetAddressSpaceOwner(AddressSpace) ? MM_LOWEST_USER_ADDRESS : MmSystemRangeStart;
+   PVOID HighestAddress = MmGetAddressSpaceOwner(AddressSpace) ?
                           (PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
 
    MmVerifyMemoryAreas(AddressSpace);
 
    Address = MM_ROUND_DOWN(Address, PAGE_SIZE);
 
-   if (AddressSpace->LowestAddress < MmSystemRangeStart)
+   if (LowestAddress < MmSystemRangeStart)
    {
       if (Address >= MmSystemRangeStart)
       {
@@ -664,7 +664,7 @@ MmFindGapAtAddress(
    }
    else
    {
-      if (Address < AddressSpace->LowestAddress)
+      if (Address < LowestAddress)
       {
          return 0;
       }
@@ -702,21 +702,6 @@ MmFindGapAtAddress(
    }
 }
 
-/**
- * @name MmInitMemoryAreas
- *
- * Initialize the memory area list implementation.
- */
-
-NTSTATUS
-INIT_FUNCTION
-NTAPI
-MmInitMemoryAreas(VOID)
-{
-   DPRINT("MmInitMemoryAreas()\n",0);
-   return(STATUS_SUCCESS);
-}
-
 
 /**
  * @name MmFreeMemoryArea
@@ -737,9 +722,9 @@ MmInitMemoryAreas(VOID)
  * @remarks Lock the address space before calling this function.
  */
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 MmFreeMemoryArea(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PMEMORY_AREA MemoryArea,
    PMM_FREE_PAGE_FUNC FreePage,
    PVOID FreePageContext)
@@ -748,11 +733,12 @@ MmFreeMemoryArea(
    ULONG_PTR Address;
    PVOID EndAddress;
    PEPROCESS CurrentProcess = PsGetCurrentProcess();
-
-   if (AddressSpace->Process != NULL &&
-       AddressSpace->Process != CurrentProcess)
+   PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+    
+   if (Process != NULL &&
+       Process != CurrentProcess)
    {
-      KeAttachProcess(&AddressSpace->Process->Pcb);
+      KeAttachProcess(&Process->Pcb);
    }
 
    EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE);
@@ -770,13 +756,13 @@ MmFreeMemoryArea(
          SWAPENTRY SwapEntry = 0;
          PFN_TYPE Page = 0;
 
-         if (MmIsPageSwapEntry(AddressSpace->Process, (PVOID)Address))
+         if (MmIsPageSwapEntry(Process, (PVOID)Address))
          {
-            MmDeletePageFileMapping(AddressSpace->Process, (PVOID)Address, &SwapEntry);
+            MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry);
          }
          else
          {
-            MmDeleteVirtualMapping(AddressSpace->Process, (PVOID)Address, FALSE, &Dirty, &Page);
+            MmDeleteVirtualMapping(Process, (PVOID)Address, FALSE, &Dirty, &Page);
          }
          if (FreePage != NULL)
          {
@@ -786,8 +772,8 @@ MmFreeMemoryArea(
       }
    }
 
-   if (AddressSpace->Process != NULL &&
-       AddressSpace->Process != CurrentProcess)
+   if (Process != NULL &&
+       Process != CurrentProcess)
    {
       KeDetachProcess();
    }
@@ -802,7 +788,7 @@ MmFreeMemoryArea(
             ParentReplace = &MemoryArea->Parent->RightChild;
       }
       else
-         ParentReplace = &AddressSpace->MemoryAreaRoot;
+         ParentReplace = (PMEMORY_AREA*)&AddressSpace->WorkingSetExpansionLinks.Flink;
 
       if (MemoryArea->RightChild == NULL)
       {
@@ -878,9 +864,9 @@ MmFreeMemoryArea(
  * @remarks Lock the address space before calling this function.
  */
 
-NTSTATUS STDCALL
+NTSTATUS NTAPI
 MmFreeMemoryAreaByPtr(
-   PMADDRESS_SPACE AddressSpace,
+   PMMSUPPORT AddressSpace,
    PVOID BaseAddress,
    PMM_FREE_PAGE_FUNC FreePage,
    PVOID FreePageContext)
@@ -897,7 +883,7 @@ MmFreeMemoryAreaByPtr(
                                             BaseAddress);
    if (MemoryArea == NULL)
    {
-      KEBUGCHECK(0);
+      KeBugCheck(MEMORY_MANAGEMENT);
       return(STATUS_UNSUCCESSFUL);
    }
 
@@ -930,8 +916,8 @@ MmFreeMemoryAreaByPtr(
  * @remarks Lock the address space before calling this function.
  */
 
-NTSTATUS STDCALL
-MmCreateMemoryArea(PMADDRESS_SPACE AddressSpace,
+NTSTATUS NTAPI
+MmCreateMemoryArea(PMMSUPPORT AddressSpace,
                    ULONG Type,
                    PVOID *BaseAddress,
                    ULONG_PTR Length,
@@ -974,17 +960,14 @@ MmCreateMemoryArea(PMADDRESS_SPACE AddressSpace,
                          - (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity));
       *BaseAddress = MM_ROUND_DOWN(*BaseAddress, Granularity);
 
-      if (AddressSpace->LowestAddress == MmSystemRangeStart &&
-          *BaseAddress < MmSystemRangeStart)
+      if (!MmGetAddressSpaceOwner(AddressSpace) && *BaseAddress < MmSystemRangeStart)
       {
-         CHECKPOINT;
          return STATUS_ACCESS_VIOLATION;
       }
 
-      if (AddressSpace->LowestAddress < MmSystemRangeStart &&
+      if (MmGetAddressSpaceOwner(AddressSpace) &&
           (ULONG_PTR)(*BaseAddress) + tmpLength > (ULONG_PTR)MmSystemRangeStart)
       {
-         CHECKPOINT;
          return STATUS_ACCESS_VIOLATION;
       }
 
@@ -1002,9 +985,28 @@ MmCreateMemoryArea(PMADDRESS_SPACE AddressSpace,
          return STATUS_CONFLICTING_ADDRESSES;
       }
    }
-
-   MemoryArea = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
-                                      TAG_MAREA);
+    
+    //
+    // 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++];
+    }
+    else
+    {
+        //
+        // Allocate the memory area from nonpaged pool
+        //
+        MemoryArea = ExAllocatePoolWithTag(NonPagedPool,
+                                           sizeof(MEMORY_AREA),
+                                           TAG_MAREA);
+    }
+    
    RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
    MemoryArea->Type = Type;
    MemoryArea->StartingAddress = *BaseAddress;
@@ -1023,10 +1025,42 @@ MmCreateMemoryArea(PMADDRESS_SPACE AddressSpace,
    return STATUS_SUCCESS;
 }
 
+VOID NTAPI
+MmMapMemoryArea(PVOID BaseAddress,
+                ULONG Length,
+                ULONG Consumer,
+                ULONG Protection)
+{
+   ULONG i;
+   NTSTATUS Status;
+
+   for (i = 0; i < PAGE_ROUND_UP(Length) / PAGE_SIZE; i++)
+   {
+      PFN_TYPE Page;
+
+      Status = MmRequestPageMemoryConsumer(Consumer, TRUE, &Page);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Unable to allocate page\n");
+         KeBugCheck(MEMORY_MANAGEMENT);
+      }
+      Status = MmCreateVirtualMapping (NULL,
+                                       (PVOID)((ULONG_PTR)BaseAddress + (i * PAGE_SIZE)),
+                                       Protection,
+                                       &Page,
+                                       1);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Unable to create virtual mapping\n");
+         KeBugCheck(MEMORY_MANAGEMENT);
+      }
+   }
+}
+
 
-VOID STDCALL
+VOID NTAPI
 MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process,
-                                 PMADDRESS_SPACE AddressSpace,
+                                 PMMSUPPORT AddressSpace,
                                  PVOID BaseAddress)
 {
    PMEMORY_AREA MemoryArea;