-/*
- * ReactOS kernel
- * Copyright (C) 1998, 1999, 2000, 2001, 2003 ReactOS Team
+/* $Id$
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-/*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/marea.c
* PURPOSE: Implements memory areas
- * PROGRAMMER: David Welch (welch@mcmail.com)
- * UPDATE HISTORY:
- * Created 22/05/98
+ *
+ * PROGRAMMERS: Rex Jolliff
+ * David Welch
+ * Eric Kohl
+ * Philip Susi
+ * Casper Hornstrup
+ * Eric Kohl
+ * Ge van Geldorp
+ * Royce Mitchell III
+ * Aleksey Bragin
+ * Jason Filby
+ * Thomas Weidenmueller
+ * Gunnar Andre' Dalsnes
+ * Mike Nordell
+ * Alex Ionescu
+ * Filip Navara
+ * Herve Poussineau
+ * Steven Edwards
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include <internal/debug.h>
-/* GLOBALS *******************************************************************/
-
-#define TAG_MAREA TAG('M', 'A', 'R', 'E')
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, MmInitMemoryAreas)
+#endif
/* #define VALIDATE_MEMORY_AREAS */
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;
}
}
/**
- * @name MmIterateFirstNode
+ * @name MmIterateLastNode
*
* @param Node
* Head node of the MEMORY_AREA tree.
}
/**
- * @name MmIterateNextNode
+ * @name MmIteratePreviousNode
*
* @param Node
* Current node in the tree.
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;
}
PMEMORY_AREA Node;
ASSERT(AddressSpace != NULL);
-
+
/* Special case for empty tree. */
if (AddressSpace->MemoryAreaRoot == NULL)
return;
}
}
#else
-#define MmVerifyMemoryAreas(x)
+#define MmVerifyMemoryAreas(x)
#endif
VOID STDCALL
PMEMORY_AREA Node;
DbgPrint("MmDumpMemoryAreas()\n");
-
+
/* Special case for empty tree. */
if (AddressSpace->MemoryAreaRoot == NULL)
return;
Node != NULL;
Node = MmIterateNextNode(Node))
{
- DbgPrint("Start %x End %x Attributes %x\n",
+ DbgPrint("Start %p End %p Protect %x Flags %x\n",
Node->StartingAddress, Node->EndingAddress,
- Node->Attributes);
+ Node->Protect, Node->Flags);
}
DbgPrint("Finished MmDumpMemoryAreas()\n");
{
PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot;
- DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
+ DPRINT("MmLocateMemoryAreaByAddress(AddressSpace %p, Address %p)\n",
AddressSpace, Address);
- if (!(KdDebugState & KD_DEBUG_SCREEN))
- MmVerifyMemoryAreas(AddressSpace);
+ MmVerifyMemoryAreas(AddressSpace);
while (Node != NULL)
{
Node = Node->RightChild;
else
{
- DPRINT("MmLocateMemoryAreaByAddress(%x): %x [%x - %x]\n",
+ DPRINT("MmLocateMemoryAreaByAddress(%p): %p [%p - %p]\n",
Address, Node, Node->StartingAddress, Node->EndingAddress);
return Node;
}
}
- DPRINT("MmLocateMemoryAreaByAddress(%x): 0\n", Address);
+ DPRINT("MmLocateMemoryAreaByAddress(%p): 0\n", Address);
return NULL;
}
if (Node->StartingAddress >= Address &&
Node->StartingAddress < Extent)
{
- DPRINT("MmLocateMemoryAreaByRegion(%x - %x): %x - %x\n",
- Address, Address + Length, Node->StartingAddress,
+ DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
+ Address, (ULONG_PTR)Address + Length, Node->StartingAddress,
Node->EndingAddress);
return Node;
}
if (Node->EndingAddress > Address &&
Node->EndingAddress < Extent)
{
- DPRINT("MmLocateMemoryAreaByRegion(%x - %x): %x - %x\n",
- Address, Address + Length, Node->StartingAddress,
+ DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
+ Address, (ULONG_PTR)Address + Length, Node->StartingAddress,
Node->EndingAddress);
return Node;
}
if (Node->StartingAddress <= Address &&
Node->EndingAddress >= Extent)
{
- DPRINT("MmLocateMemoryAreaByRegion(%x - %x): %x - %x\n",
- Address, Address + Length, Node->StartingAddress,
+ DPRINT("MmLocateMemoryAreaByRegion(%p - %p): %p - %p\n",
+ Address, (ULONG_PTR)Address + Length, Node->StartingAddress,
Node->EndingAddress);
return Node;
}
* @name MmCompressHelper
*
* This is helper of MmRebalanceTree. Performs a compression transformation
- * count times, starting at root.
+ * count times, starting at root.
*/
static VOID
MmCompressHelper(
PMADDRESS_SPACE AddressSpace,
- ULONG Count)
+ ULONG Count)
{
PMEMORY_AREA Root = NULL;
PMEMORY_AREA Red = AddressSpace->MemoryAreaRoot;
CurrentNode = AddressSpace->MemoryAreaRoot;
while (CurrentNode != NULL)
{
- if (CurrentNode->RightChild == NULL)
+ if (CurrentNode->RightChild == NULL)
{
PreviousNode = CurrentNode;
CurrentNode = CurrentNode->LeftChild;
NodeCount++;
}
- else
+ else
{
TempNode = CurrentNode->RightChild;
/* Transform Vine back into a balanced tree. */
Leaves = NodeCount + 1;
- for (;;)
+ for (;;)
{
ULONG Next = Leaves & (Leaves - 1);
if (Next == 0)
Vine = NodeCount - Leaves;
Height = 1 + (Leaves > 0);
- while (Vine > 1)
+ while (Vine > 1)
{
MmCompressHelper(AddressSpace, Vine / 2);
Vine /= 2;
Node = AddressSpace->MemoryAreaRoot;
do
{
- DPRINT("marea->EndingAddress: %x Node->StartingAddress: %x\n",
+ DPRINT("marea->EndingAddress: %p Node->StartingAddress: %p\n",
marea->EndingAddress, Node->StartingAddress);
- DPRINT("marea->StartingAddress: %x Node->EndingAddress: %x\n",
+ DPRINT("marea->StartingAddress: %p Node->EndingAddress: %p\n",
marea->StartingAddress, Node->EndingAddress);
ASSERT(marea->EndingAddress <= Node->StartingAddress ||
marea->StartingAddress >= Node->EndingAddress);
ASSERT(marea->StartingAddress != Node->StartingAddress);
-
+
PreviousNode = Node;
-
+
if (marea->StartingAddress < Node->StartingAddress)
Node = Node->LeftChild;
else
Node = Node->RightChild;
-
+
if (Node)
{
Depth++;
ULONG_PTR Length,
ULONG_PTR Granularity)
{
- PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ?
- (PVOID)(KERNEL_BASE - 1) : (PVOID)MAXULONG_PTR;
+ PVOID HighestAddress = AddressSpace->LowestAddress < MmSystemRangeStart ?
+ (PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
PVOID AlignedAddress;
PMEMORY_AREA Node;
PMEMORY_AREA FirstNode;
MmVerifyMemoryAreas(AddressSpace);
- DPRINT("LowestAddress: %x HighestAddress: %x\n",
+ DPRINT("LowestAddress: %p HighestAddress: %p\n",
AddressSpace->LowestAddress, HighestAddress);
AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
/* Special case for empty tree. */
if (AddressSpace->MemoryAreaRoot == NULL)
{
- if (HighestAddress - AlignedAddress >= Length)
+ if ((ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
{
- DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress);
+ DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
DPRINT("MmFindGapBottomUp: 0\n");
AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity);
if (Node->StartingAddress > AlignedAddress &&
- Node->StartingAddress - AlignedAddress >= Length)
+ (ULONG_PTR)Node->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
{
- DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress);
+ DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
/* Check if there is enough space after the last memory area. */
AlignedAddress = MM_ROUND_UP(PreviousNode->EndingAddress, Granularity);
- if (HighestAddress - AlignedAddress >= Length)
+ if ((ULONG_PTR)HighestAddress > (ULONG_PTR)AlignedAddress &&
+ (ULONG_PTR)HighestAddress - (ULONG_PTR)AlignedAddress >= Length)
{
- DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress);
+ DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
/* Check if there is enough space before the first memory area. */
AlignedAddress = MM_ROUND_UP(AddressSpace->LowestAddress, Granularity);
if (FirstNode->StartingAddress > AlignedAddress &&
- FirstNode->StartingAddress - AlignedAddress >= Length)
+ (ULONG_PTR)FirstNode->StartingAddress - (ULONG_PTR)AlignedAddress >= Length)
{
- DPRINT("MmFindGapBottomUp: %x\n", AlignedAddress);
+ DPRINT("MmFindGapBottomUp: %p\n", AlignedAddress);
return AlignedAddress;
}
ULONG_PTR Length,
ULONG_PTR Granularity)
{
- PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ?
- (PVOID)(KERNEL_BASE - 1) : (PVOID)MAXULONG_PTR;
+ PVOID HighestAddress = AddressSpace->LowestAddress < MmSystemRangeStart ?
+ (PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
PVOID AlignedAddress;
PMEMORY_AREA Node;
PMEMORY_AREA PreviousNode;
MmVerifyMemoryAreas(AddressSpace);
- DPRINT("LowestAddress: %x HighestAddress: %x\n",
+ DPRINT("LowestAddress: %p HighestAddress: %p\n",
AddressSpace->LowestAddress, HighestAddress);
- AlignedAddress = MM_ROUND_DOWN(HighestAddress - Length + 1, Granularity);
+ AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)HighestAddress - Length + 1, Granularity);
/* Check for overflow. */
if (AlignedAddress > HighestAddress)
{
if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress)
{
- DPRINT("MmFindGapTopDown: %x\n", AlignedAddress);
+ DPRINT("MmFindGapTopDown: %p\n", AlignedAddress);
return AlignedAddress;
}
DPRINT("MmFindGapTopDown: 0\n");
/* Check if there is enough space after the last memory area. */
if (Node->EndingAddress <= AlignedAddress)
{
- DPRINT("MmFindGapTopDown: %x\n", AlignedAddress);
+ DPRINT("MmFindGapTopDown: %p\n", AlignedAddress);
return AlignedAddress;
}
if (Node == NULL)
break;
- AlignedAddress = MM_ROUND_DOWN(PreviousNode->StartingAddress - Length + 1, Granularity);
+ AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)PreviousNode->StartingAddress - Length + 1, Granularity);
/* Check for overflow. */
if (AlignedAddress > PreviousNode->StartingAddress)
return NULL;
-
+
if (Node->EndingAddress <= AlignedAddress)
{
- DPRINT("MmFindGapTopDown: %x\n", AlignedAddress);
+ DPRINT("MmFindGapTopDown: %p\n", AlignedAddress);
return AlignedAddress;
}
PreviousNode = Node;
}
- AlignedAddress = MM_ROUND_DOWN(PreviousNode->StartingAddress - Length + 1, Granularity);
+ AlignedAddress = MM_ROUND_DOWN((ULONG_PTR)PreviousNode->StartingAddress - Length + 1, Granularity);
/* Check for overflow. */
if (AlignedAddress > PreviousNode->StartingAddress)
if (AlignedAddress >= (PVOID)AddressSpace->LowestAddress)
{
- DPRINT("MmFindGapTopDown: %x\n", AlignedAddress);
+ DPRINT("MmFindGapTopDown: %p\n", AlignedAddress);
return AlignedAddress;
}
{
PMEMORY_AREA Node = AddressSpace->MemoryAreaRoot;
PMEMORY_AREA RightNeighbour = NULL;
- PVOID HighestAddress = AddressSpace->LowestAddress < (PVOID)KERNEL_BASE ?
- (PVOID)(KERNEL_BASE - 1) : (PVOID)MAXULONG_PTR;
+ PVOID HighestAddress = AddressSpace->LowestAddress < MmSystemRangeStart ?
+ (PVOID)((ULONG_PTR)MmSystemRangeStart - 1) : (PVOID)MAXULONG_PTR;
MmVerifyMemoryAreas(AddressSpace);
Address = MM_ROUND_DOWN(Address, PAGE_SIZE);
- if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE)
+ if (AddressSpace->LowestAddress < MmSystemRangeStart)
{
- if (Address >= (PVOID)KERNEL_BASE)
+ if (Address >= MmSystemRangeStart)
{
return 0;
}
if (RightNeighbour)
{
- DPRINT("MmFindGapAtAddress: %x [%x]\n", Address, RightNeighbour->StartingAddress - Address);
- return RightNeighbour->StartingAddress - Address;
+ DPRINT("MmFindGapAtAddress: %p [%p]\n", Address,
+ (ULONG_PTR)RightNeighbour->StartingAddress - (ULONG_PTR)Address);
+ return (ULONG_PTR)RightNeighbour->StartingAddress - (ULONG_PTR)Address;
}
else
{
- DPRINT("MmFindGapAtAddress: %x [%x]\n", Address, HighestAddress - Address);
- return HighestAddress - Address;
+ DPRINT("MmFindGapAtAddress: %p [%p]\n", Address,
+ (ULONG_PTR)HighestAddress - (ULONG_PTR)Address);
+ return (ULONG_PTR)HighestAddress - (ULONG_PTR)Address;
}
}
* Initialize the memory area list implementation.
*/
-NTSTATUS INIT_FUNCTION
+NTSTATUS
+INIT_FUNCTION
+NTAPI
MmInitMemoryAreas(VOID)
{
DPRINT("MmInitMemoryAreas()\n",0);
*
* Free an existing memory area.
*
- * @param AddressSpace
+ * @param AddressSpace
* Address space to free the area from.
* @param MemoryArea
* Memory area we're about to free.
PVOID FreePageContext)
{
PMEMORY_AREA *ParentReplace;
- PVOID Address;
+ ULONG_PTR Address;
PVOID EndAddress;
- PEPROCESS CurrentProcess = PsGetCurrentProcess();
+ PROS_EPROCESS CurrentProcess = (PROS_EPROCESS)PsGetCurrentProcess();
if (AddressSpace->Process != NULL &&
AddressSpace->Process != CurrentProcess)
KeAttachProcess(&AddressSpace->Process->Pcb);
}
- EndAddress = MM_ROUND_UP(MemoryArea->EndingAddress, PAGE_SIZE);
- for (Address = MemoryArea->StartingAddress; Address < EndAddress; Address += PAGE_SIZE)
+ 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)
{
}
else
{
- BOOL Dirty = FALSE;
+ BOOLEAN Dirty = FALSE;
SWAPENTRY SwapEntry = 0;
PFN_TYPE Page = 0;
KeDetachProcess();
}
- /* Remove the tree item. */
+ /* Remove the tree item. */
{
if (MemoryArea->Parent != NULL)
{
}
}
- ExFreePool(MemoryArea);
+ ExFreePoolWithTag(MemoryArea, TAG_MAREA);
DPRINT("MmFreeMemoryAreaByNode() succeeded\n");
*
* Free an existing memory area given a pointer inside it.
*
- * @param AddressSpace
+ * @param AddressSpace
* Address space to free the area from.
* @param BaseAddress
* Address in the memory area we're about to free.
{
PMEMORY_AREA MemoryArea;
- DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, "
- "FreePageContext %d)\n", AddressSpace, BaseAddress,
+ DPRINT("MmFreeMemoryArea(AddressSpace %p, BaseAddress %p, "
+ "FreePageContext %p)\n", AddressSpace, BaseAddress,
FreePageContext);
MmVerifyMemoryAreas(AddressSpace);
*
* Create a memory area.
*
- * @param AddressSpace
+ * @param AddressSpace
* Address space to create the area in.
* @param Type
* Type of the memory area.
*/
NTSTATUS STDCALL
-MmCreateMemoryArea(PEPROCESS Process,
- PMADDRESS_SPACE AddressSpace,
+MmCreateMemoryArea(PMADDRESS_SPACE AddressSpace,
ULONG Type,
PVOID *BaseAddress,
ULONG_PTR Length,
- ULONG Attributes,
+ ULONG Protect,
PMEMORY_AREA *Result,
BOOLEAN FixedAddress,
- BOOLEAN TopDown,
+ ULONG AllocationFlags,
PHYSICAL_ADDRESS BoundaryAddressMultiple)
{
PVOID EndAddress;
ULONG tmpLength;
PMEMORY_AREA MemoryArea;
- DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x, "
- "*BaseAddress %x, Length %x, Attributes %x, TopDown: %x, "
- "FixedAddress %x, Result %x)\n",
+ DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %p, "
+ "*BaseAddress %p, Length %p, Attributes %x, TopDown: %x, "
+ "FixedAddress %x, Result %p)\n",
Type, BaseAddress, *BaseAddress, Length, Attributes, TopDown,
FixedAddress, Result);
*BaseAddress = MmFindGap(AddressSpace,
tmpLength,
Granularity,
- TopDown != 0);
+ (AllocationFlags & MEM_TOP_DOWN) == MEM_TOP_DOWN);
if ((*BaseAddress) == 0)
{
DPRINT("No suitable gap\n");
- (ULONG_PTR) MM_ROUND_DOWN(*BaseAddress, Granularity));
*BaseAddress = MM_ROUND_DOWN(*BaseAddress, Granularity);
- if (AddressSpace->LowestAddress == (PVOID)KERNEL_BASE &&
- *BaseAddress < (PVOID)KERNEL_BASE)
+ if (AddressSpace->LowestAddress == MmSystemRangeStart &&
+ *BaseAddress < MmSystemRangeStart)
{
CHECKPOINT;
return STATUS_ACCESS_VIOLATION;
}
- if (AddressSpace->LowestAddress < (PVOID)KERNEL_BASE &&
- (ULONG_PTR)(*BaseAddress) + tmpLength > KERNEL_BASE)
+ if (AddressSpace->LowestAddress < MmSystemRangeStart &&
+ (ULONG_PTR)(*BaseAddress) + tmpLength > (ULONG_PTR)MmSystemRangeStart)
{
CHECKPOINT;
return STATUS_ACCESS_VIOLATION;
RtlZeroMemory(MemoryArea, sizeof(MEMORY_AREA));
MemoryArea->Type = Type;
MemoryArea->StartingAddress = *BaseAddress;
- MemoryArea->EndingAddress = *BaseAddress + tmpLength;
- MemoryArea->Attributes = Attributes;
+ MemoryArea->EndingAddress = (PVOID)((ULONG_PTR)*BaseAddress + tmpLength);
+ MemoryArea->Protect = Protect;
+ MemoryArea->Flags = AllocationFlags;
MemoryArea->LockCount = 0;
- MemoryArea->Process = Process;
MemoryArea->PageOpCount = 0;
MemoryArea->DeleteInProgress = FALSE;
*Result = MemoryArea;
- DPRINT("MmCreateMemoryArea() succeeded (%x)\n", *BaseAddress);
+ DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
return STATUS_SUCCESS;
}
VOID STDCALL
-MmReleaseMemoryAreaIfDecommitted(PEPROCESS Process,
+MmReleaseMemoryAreaIfDecommitted(PROS_EPROCESS Process,
PMADDRESS_SPACE AddressSpace,
PVOID BaseAddress)
{
PLIST_ENTRY Entry;
PMM_REGION Region;
BOOLEAN Reserved;
-
+
MmVerifyMemoryAreas(AddressSpace);
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, BaseAddress);