Author: tkreuzer
Date: Sun May 17 00:35:37 2015
New Revision: 67797
URL:
http://svn.reactos.org/svn/reactos?rev=67797&view=rev
Log:
[NTOSKRNL]
Add a tiny hack to MiFindEmptyAddressRangeInTree and MiFindEmptyAddressRangeDownTree to
support VADs in the kernel VA range. Make MmFindGap use those functions to look for free
space.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c
trunk/reactos/ntoskrnl/mm/marea.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/vadnode.c [iso-8859-1] Sun May 17 00:35:37 2015
@@ -506,13 +506,19 @@
OUT PULONG_PTR Base)
{
PMMADDRESS_NODE Node, PreviousNode;
- ULONG_PTR PageCount, AlignmentVpn, LowVpn, HighVpn;
+ ULONG_PTR PageCount, AlignmentVpn, LowVpn, HighestVpn;
ASSERT(Length != 0);
/* Calculate page numbers for the length, alignment, and starting address */
PageCount = BYTES_TO_PAGES(Length);
AlignmentVpn = Alignment >> PAGE_SHIFT;
LowVpn = ALIGN_UP_BY((ULONG_PTR)MM_LOWEST_USER_ADDRESS >> PAGE_SHIFT,
AlignmentVpn);
+
+ /* Check for kernel mode table (memory areas) */
+ if (Table->Unused == 1)
+ {
+ LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT,
AlignmentVpn);
+ }
/* Check if the table is empty */
if (Table->NumberGenericTableElements == 0)
@@ -566,8 +572,15 @@
}
/* We're up to the highest VAD, will this allocation fit above it? */
- HighVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) / PAGE_SIZE;
- if (HighVpn >= LowVpn + PageCount)
+ HighestVpn = ((ULONG_PTR)MM_HIGHEST_VAD_ADDRESS + 1) / PAGE_SIZE;
+
+ /* Check for kernel mode table (memory areas) */
+ if (Table->Unused == 1)
+ {
+ HighestVpn = ALIGN_UP_BY((ULONG_PTR)(LONG_PTR)-1 >> PAGE_SHIFT,
AlignmentVpn);
+ }
+
+ if (HighestVpn >= LowVpn + PageCount)
{
/* Yes! Use this VAD to store the allocation */
*PreviousVad = PreviousNode;
@@ -602,9 +615,18 @@
PageCount = Length >> PAGE_SHIFT;
AlignmentVpn = Alignment / PAGE_SIZE;
+ /* Check for kernel mode table (memory areas) */
+ if (Table->Unused == 1)
+ {
+ LowVpn = ALIGN_UP_BY((ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT,
AlignmentVpn);
+ }
+ else
+ {
+ LowVpn = ALIGN_UP_BY((ULONG_PTR)MM_LOWEST_USER_ADDRESS, Alignment);
+ }
+
/* Check if there is enough space below the boundary */
- if ((ALIGN_UP_BY((ULONG_PTR)MM_LOWEST_USER_ADDRESS, Alignment) + Length) >
- (BoundaryAddress + 1))
+ if ((LowVpn + Length) > (BoundaryAddress + 1))
{
return TableFoundNode;
}
Modified: trunk/reactos/ntoskrnl/mm/marea.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/marea.c?rev=67…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/marea.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/marea.c [iso-8859-1] Sun May 17 00:35:37 2015
@@ -455,6 +455,7 @@
/* Build a lame VAD if this is a user-space allocation */
if (MA_GetEndingAddress(marea) < (ULONG_PTR)MmSystemRangeStart)
{
+ ASSERT(Process != NULL);
if (marea->Type != MEMORY_AREA_OWNED_BY_ARM3)
{
ASSERT(marea->Type == MEMORY_AREA_SECTION_VIEW || marea->Type ==
MEMORY_AREA_CACHE);
@@ -468,9 +469,12 @@
}
else
{
+ ASSERT(Process == NULL);
+
if (!MiRosKernelVadRootInitialized)
{
MiRosKernelVadRoot.BalancedRoot.u1.Parent =
&MiRosKernelVadRoot.BalancedRoot;
+ MiRosKernelVadRoot.Unused = 1;
MiRosKernelVadRootInitialized = TRUE;
}
@@ -526,148 +530,6 @@
PreviousNode->RightChild = marea;
}
-static PVOID
-MmFindGapBottomUp(
- PMMSUPPORT AddressSpace,
- ULONG_PTR Length,
- ULONG_PTR Granularity)
-{
- ULONG_PTR LowestAddress, HighestAddress, Candidate;
- PMEMORY_AREA Root, Node;
-
- /* Get the margins of the address space */
- if (MmGetAddressSpaceOwner(AddressSpace) != NULL)
- {
- LowestAddress = (ULONG_PTR)MM_LOWEST_USER_ADDRESS;
- HighestAddress = (ULONG_PTR)MmHighestUserAddress;
- }
- else
- {
- LowestAddress = (ULONG_PTR)MmSystemRangeStart;
- HighestAddress = MAXULONG_PTR;
- }
-
- /* Start with the lowest address */
- Candidate = LowestAddress;
-
- /* Check for overflow */
- if ((Candidate + Length) < Candidate) return NULL;
-
- /* Get the root of the address space tree */
- Root = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-
- /* Go to the node with lowest address in the tree. */
- Node = Root ? MmIterateFirstNode(Root) : NULL;
- while (Node && ((ULONG_PTR)MA_GetEndingAddress(Node) < LowestAddress))
- {
- Node = MmIterateNextNode(Node);
- }
-
- /* Traverse the tree from low to high addresses */
- while (Node && ((ULONG_PTR)MA_GetEndingAddress(Node) < HighestAddress))
- {
- /* Check if the memory area fits before the current node */
- if (MA_GetStartingAddress(Node) >= (Candidate + Length))
- {
- DPRINT("MmFindGapBottomUp: %p\n", Candidate);
- ASSERT(Candidate >= LowestAddress);
- return (PVOID)Candidate;
- }
-
- /* Calculate next possible adress above this node */
- Candidate = ALIGN_UP_BY((ULONG_PTR)MA_GetEndingAddress(Node), Granularity);
-
- /* Check for overflow */
- if ((Candidate + Length) < (ULONG_PTR)MA_GetEndingAddress(Node)) return NULL;
-
- /* Go to the next higher node */
- Node = MmIterateNextNode(Node);
- }
-
- /* Check if there is enough space after the last memory area. */
- if ((Candidate + Length) <= HighestAddress)
- {
- DPRINT("MmFindGapBottomUp: %p\n", Candidate);
- ASSERT(Candidate >= LowestAddress);
- return (PVOID)Candidate;
- }
-
- DPRINT("MmFindGapBottomUp: 0\n");
- return NULL;
-}
-
-
-static PVOID
-MmFindGapTopDown(
- PMMSUPPORT AddressSpace,
- ULONG_PTR Length,
- ULONG_PTR Granularity)
-{
- ULONG_PTR LowestAddress, HighestAddress, Candidate;
- PMEMORY_AREA Root, Node;
-
- /* Get the margins of the address space */
- if (MmGetAddressSpaceOwner(AddressSpace) != NULL)
- {
- LowestAddress = (ULONG_PTR)MM_LOWEST_USER_ADDRESS;
- HighestAddress = (ULONG_PTR)MmHighestUserAddress;
- }
- else
- {
- LowestAddress = (ULONG_PTR)MmSystemRangeStart;
- HighestAddress = MAXULONG_PTR;
- }
-
- /* Calculate the highest candidate */
- Candidate = ALIGN_DOWN_BY(HighestAddress + 1 - Length, Granularity);
-
- /* Check for overflow. */
- if (Candidate > HighestAddress) return NULL;
-
- /* Get the root of the address space tree */
- Root = (PMEMORY_AREA)AddressSpace->WorkingSetExpansionLinks.Flink;
-
- /* Go to the node with highest address in the tree. */
- Node = Root ? MmIterateLastNode(Root) : NULL;
- while (Node && (MA_GetStartingAddress(Node) > HighestAddress))
- {
- Node = MmIteratePrevNode(Node);
- }
-
- /* Traverse the tree from high to low addresses */
- while (Node && (MA_GetStartingAddress(Node) > LowestAddress))
- {
- /* Check if the memory area fits after the current node */
- if ((ULONG_PTR)MA_GetEndingAddress(Node) <= Candidate)
- {
- DPRINT("MmFindGapTopDown: %p\n", Candidate);
- return (PVOID)Candidate;
- }
-
- /* Calculate next possible adress below this node */
- Candidate = ALIGN_DOWN_BY(MA_GetStartingAddress(Node) - Length,
- Granularity);
-
- /* Check for overflow. */
- if (Candidate > MA_GetStartingAddress(Node))
- return NULL;
-
- /* Go to the next lower node */
- Node = MmIteratePrevNode(Node);
- }
-
- /* Check if the last candidate is inside the given range */
- if (Candidate >= LowestAddress)
- {
- DPRINT("MmFindGapTopDown: %p\n", Candidate);
- return (PVOID)Candidate;
- }
-
- DPRINT("MmFindGapTopDown: 0\n");
- return NULL;
-}
-
-
PVOID NTAPI
MmFindGap(
PMMSUPPORT AddressSpace,
@@ -675,10 +537,45 @@
ULONG_PTR Granularity,
BOOLEAN TopDown)
{
+ PEPROCESS Process;
+ PMM_AVL_TABLE VadRoot;
+ TABLE_SEARCH_RESULT Result;
+ PMMADDRESS_NODE Parent;
+ ULONG_PTR StartingAddress, HighestAddress;
+
+ Process = MmGetAddressSpaceOwner(AddressSpace);
+ VadRoot = Process ? &Process->VadRoot : &MiRosKernelVadRoot;
if (TopDown)
- return MmFindGapTopDown(AddressSpace, Length, Granularity);
-
- return MmFindGapBottomUp(AddressSpace, Length, Granularity);
+ {
+ /* Find an address top-down */
+ HighestAddress = Process ? (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS : (LONG_PTR)-1;
+ Result = MiFindEmptyAddressRangeDownTree(Length,
+ HighestAddress,
+ Granularity,
+ VadRoot,
+ &StartingAddress,
+ &Parent);
+ if (Result == TableFoundNode)
+ {
+ return NULL;
+ }
+
+ return (PVOID)StartingAddress;
+ }
+ else
+ {
+ Result = MiFindEmptyAddressRangeInTree(Length,
+ Granularity,
+ VadRoot,
+ &Parent,
+ &StartingAddress);
+ if (Result == TableFoundNode)
+ {
+ return NULL;
+ }
+
+ return (PVOID)StartingAddress;
+ }
}
VOID