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=677... ============================================================================== --- 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