Author: jgardou Date: Mon Feb 20 20:51:18 2012 New Revision: 55763
URL: http://svn.reactos.org/svn/reactos?rev=55763&view=rev Log: [NTOSKRNL/MM] - Stop leaking references to PDEs. Still one reference left to the TLB mapping at process deletion.
Modified: trunk/reactos/ntoskrnl/mm/anonmem.c trunk/reactos/ntoskrnl/mm/balance.c trunk/reactos/ntoskrnl/mm/i386/page.c trunk/reactos/ntoskrnl/mm/marea.c trunk/reactos/ntoskrnl/mm/section.c
Modified: trunk/reactos/ntoskrnl/mm/anonmem.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/anonmem.c?rev=5... ============================================================================== --- trunk/reactos/ntoskrnl/mm/anonmem.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/anonmem.c [iso-8859-1] Mon Feb 20 20:51:18 2012 @@ -113,6 +113,12 @@ MmCreatePageFileMapping(Process, Address, SwapEntry); MmSetSavedSwapEntryPage(Page, 0); } +#if (_MI_PAGING_LEVELS == 2) + else if(Address < MmSystemRangeStart) + { + AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--; + } +#endif MmUnlockAddressSpace(AddressSpace); MmReleasePageMemoryConsumer(MC_USER, Page); PageOp->Status = STATUS_SUCCESS; @@ -191,6 +197,9 @@ PMM_REGION Region; PMM_PAGEOP PageOp; PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); +#if (_MI_PAGING_LEVELS == 2) + BOOLEAN refPde = TRUE; +#endif
/* * There is a window between taking the page fault and locking the @@ -326,7 +335,17 @@ KeBugCheck(MEMORY_MANAGEMENT); } MmSetSavedSwapEntryPage(Page, SwapEntry); - } + +#if (_MI_PAGING_LEVELS == 2) + /* PTE was already "created", no need to reference PDE */ + refPde = FALSE; +#endif + } +#if (_MI_PAGING_LEVELS == 2) + /* Add an additional page table reference */ + if(refPde) MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; + ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT); +#endif
/* * Set the page. If we fail because we are out of memory then @@ -337,16 +356,6 @@ Region->Protect, &Page, 1); - while (Status == STATUS_NO_MEMORY) - { - MmUnlockAddressSpace(AddressSpace); - Status = MmCreateVirtualMapping(Process, - (PVOID)PAGE_ROUND_DOWN(Address), - Region->Protect, - &Page, - 1); - MmLockAddressSpace(AddressSpace); - } if (!NT_SUCCESS(Status)) { DPRINT1("MmCreateVirtualMapping failed, not out of memory\n"); @@ -393,9 +402,9 @@ for (i=0; i < PAGE_ROUND_UP(RegionSize)/PAGE_SIZE; i++) { PFN_NUMBER Page; - - if (MmIsPageSwapEntry(Process, - (char*)BaseAddress + (i * PAGE_SIZE))) + PVOID Address = (char*)BaseAddress + (i*PAGE_SIZE); + + if (MmIsPageSwapEntry(Process, Address)) { SWAPENTRY SwapEntry;
@@ -403,11 +412,17 @@ (char*)BaseAddress + (i * PAGE_SIZE), &SwapEntry); MmFreeSwapPage(SwapEntry); +#if (_MI_PAGING_LEVELS == 2) + if(Address < MmSystemRangeStart) + { + AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--; + } +#endif } else { MmDeleteVirtualMapping(Process, - (char*)BaseAddress + (i*PAGE_SIZE), + Address, FALSE, NULL, &Page); if (Page != 0) { @@ -417,10 +432,16 @@ { MmFreeSwapPage(SavedSwapEntry); MmSetSavedSwapEntryPage(Page, 0); - } + } MmDeleteRmap(Page, Process, (char*)BaseAddress + (i * PAGE_SIZE)); MmReleasePageMemoryConsumer(MC_USER, Page); +#if (_MI_PAGING_LEVELS == 2) + if(Address < MmSystemRangeStart) + { + AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--; + } +#endif } } }
Modified: trunk/reactos/ntoskrnl/mm/balance.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/balance.c?rev=5... ============================================================================== --- trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] Mon Feb 20 20:51:18 2012 @@ -14,6 +14,8 @@ #define NDEBUG #include <debug.h>
+#include "ARM3/miarm.h" + #if defined (ALLOC_PRAGMA) #pragma alloc_text(INIT, MmInitializeBalancer) #pragma alloc_text(INIT, MmInitializeMemoryConsumer) @@ -234,8 +236,38 @@
VOID NTAPI +MiDeletePte(IN PMMPTE PointerPte, + IN PVOID VirtualAddress, + IN PEPROCESS CurrentProcess, + IN PMMPTE PrototypePte); + +VOID +NTAPI MmRebalanceMemoryConsumers(VOID) { +#if (_MI_PAGING_LEVELS == 2) + if(!MiIsBalancerThread()) + { + /* Clean up the unused PDEs */ + ULONG_PTR Address; + KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + PMMPDE pointerPde; + for(Address = (ULONG_PTR)MI_LOWEST_VAD_ADDRESS; + Address < (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS; + Address += (PAGE_SIZE * PTE_COUNT)) + { + if(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] == 0) + { + pointerPde = MiAddressToPde(Address); + if(pointerPde->u.Hard.Valid) + MiDeletePte(pointerPde, MiPdeToPte(pointerPde), PsGetCurrentProcess(), NULL); + ASSERT(pointerPde->u.Hard.Valid == 0); + } + } + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + } +#endif + if (MiBalancerThreadHandle != NULL && !MiIsBalancerThread()) {
Modified: trunk/reactos/ntoskrnl/mm/i386/page.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?rev... ============================================================================== --- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Mon Feb 20 20:51:18 2012 @@ -258,9 +258,22 @@ { /* Nobody but page fault should ask for creating the PDE, * Which imples that Process is the current one */ - ASSERT(Create == FALSE); MmDeleteHyperspaceMapping(PdeBase); - return NULL; + if(Create == FALSE) + return NULL; + else + { + KAPC_STATE ApcState; + PULONG ret; + /* Attach to process */ + KeStackAttachProcess(&Process->Pcb, &ApcState); + + /* Retry */ + ret = MmGetPageTableForProcess(Process, Address, TRUE); + + /* Get Back to original process */ + KeUnstackDetachProcess(&ApcState); + } } else { @@ -293,6 +306,7 @@ }
/* This is for kernel land address */ + ASSERT(Process == NULL); PointerPde = MiAddressToPde(Address); Pt = (PULONG)MiAddressToPte(Address); if (PointerPde->u.Hard.Valid == 0)
Modified: trunk/reactos/ntoskrnl/mm/marea.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/marea.c?rev=557... ============================================================================== --- trunk/reactos/ntoskrnl/mm/marea.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/marea.c [iso-8859-1] Mon Feb 20 20:51:18 2012 @@ -44,6 +44,8 @@ #include <ntoskrnl.h> #define NDEBUG #include <debug.h> + +#include "ARM3/miarm.h"
MEMORY_AREA MiStaticMemoryAreas[MI_STATIC_MEMORY_AREAS]; ULONG MiStaticMemoryAreaCount; @@ -688,6 +690,12 @@ * * @remarks Lock the address space before calling this function. */ +VOID +NTAPI +MiDeletePte(IN PMMPTE PointerPte, + IN PVOID VirtualAddress, + IN PEPROCESS CurrentProcess, + IN PMMPTE PrototypePte);
NTSTATUS NTAPI MmFreeMemoryArea( @@ -716,10 +724,10 @@ Address < (ULONG_PTR)EndAddress; Address += PAGE_SIZE) { - BOOLEAN Dirty = FALSE; - SWAPENTRY SwapEntry = 0; - PFN_NUMBER Page = 0; - + BOOLEAN Dirty = FALSE; + SWAPENTRY SwapEntry = 0; + PFN_NUMBER Page = 0; + if (MmIsPageSwapEntry(Process, (PVOID)Address)) { MmDeletePageFileMapping(Process, (PVOID)Address, &SwapEntry); @@ -733,6 +741,25 @@ FreePage(FreePageContext, MemoryArea, (PVOID)Address, Page, SwapEntry, (BOOLEAN)Dirty); } +#if (_MI_PAGING_LEVELS == 2) + /* Remove page table reference */ + if((SwapEntry || Page) && ((PVOID)Address < MmSystemRangeStart)) + { + ASSERT(AddressSpace != MmGetKernelAddressSpace()); + MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--; + ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] < PTE_COUNT); + if(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] == 0) + { + /* No PTE relies on this PDE. Release it */ + KIRQL OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + PMMPDE PointerPde = MiAddressToPde(Address); + ASSERT(PointerPde->u.Hard.Valid == 1); + MiDeletePte(PointerPde, MiPdeToPte(PointerPde), Process, NULL); + ASSERT(PointerPde->u.Hard.Valid == 0); + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + } + } +#endif }
if (Process != NULL &&
Modified: trunk/reactos/ntoskrnl/mm/section.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=5... ============================================================================== --- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original) +++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Mon Feb 20 20:51:18 2012 @@ -57,6 +57,8 @@ #pragma alloc_text(INIT, MmInitSectionImplementation) #endif
+#include "ARM3/miarm.h" + NTSTATUS NTAPI MiMapViewInSystemSpace(IN PVOID Section, @@ -1448,6 +1450,15 @@ Page = PFN_FROM_SSE(Entry);
MmSharePageEntrySectionSegment(Segment, Offset); + + #if (_MI_PAGING_LEVELS == 2) + /* Reference Page Directory Entry */ + if(Address < MmSystemRangeStart) + { + MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; + ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT); + } +#endif
/* FIXME: Should we call MmCreateVirtualMappingUnsafe if * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true? @@ -1538,6 +1549,15 @@ return(STATUS_SUCCESS); }
+#if (_MI_PAGING_LEVELS == 2) + /* Reference Page Directory Entry */ + if(Address < MmSystemRangeStart) + { + MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; + ASSERT(MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)] <= PTE_COUNT); + } +#endif + /* * Satisfying a page fault on a map of /Device/PhysicalMemory is easy */ @@ -1658,6 +1678,12 @@ /* * Cleanup and release locks */ +#if (_MI_PAGING_LEVELS == 2) + if(Address < MmSystemRangeStart) + { + MmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--; + } +#endif MmLockAddressSpace(AddressSpace); PageOp->Status = Status; MmspCompleteAndReleasePageOp(PageOp); @@ -1876,7 +1902,10 @@ MmSetPageProtect(Process, Address, Region->Protect); return(STATUS_SUCCESS); } - + + if(OldPage == 0) + DPRINT("OldPage == 0!\n"); + /* * Get or create a pageop */ @@ -1986,7 +2015,7 @@ MM_SECTION_PAGEOUT_CONTEXT* PageOutContext; BOOLEAN WasDirty; PFN_NUMBER Page; - + PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context; if (Process) { @@ -2021,6 +2050,14 @@ { MmReleasePageMemoryConsumer(MC_USER, Page); } + +#if (_MI_PAGING_LEVELS == 2) + if(Address < MmSystemRangeStart) + { + if(Process->VmDeleted) DPRINT1("deleted!!!"); + Process->Vm.VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]--; + } +#endif
DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address); } @@ -2254,6 +2291,13 @@ { MmSetSavedSwapEntryPage(Page, 0); MmLockAddressSpace(AddressSpace); + #if (_MI_PAGING_LEVELS == 2) + /* Page table was dereferenced while deleting the RMAP */ + if(Address < MmSystemRangeStart) + { + AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; + } +#endif Status = MmCreatePageFileMapping(Process, Address, SwapEntry); @@ -2281,6 +2325,13 @@ /* * For private pages restore the old mappings. */ + #if (_MI_PAGING_LEVELS == 2) + /* Page table was dereferenced while deleting the RMAP */ + if(Address < MmSystemRangeStart) + { + AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; + } +#endif if (Context.Private) { Status = MmCreateVirtualMapping(Process, @@ -2331,6 +2382,13 @@ * As above: undo our actions. * FIXME: Also free the swap page. */ +#if (_MI_PAGING_LEVELS == 2) + /* Page table was dereferenced while deleting the RMAP */ + if(Address < MmSystemRangeStart) + { + AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; + } +#endif MmLockAddressSpace(AddressSpace); if (Context.Private) { @@ -2382,6 +2440,13 @@ if (Context.Private) { MmLockAddressSpace(AddressSpace); + #if (_MI_PAGING_LEVELS == 2) + /* Page table was dereferenced while deleting the RMAP */ + if(Address < MmSystemRangeStart) + { + AddressSpace->VmWorkingSetList->UsedPageTableEntries[MiGetPdeOffset(Address)]++; + } +#endif Status = MmCreatePageFileMapping(Process, Address, SwapEntry);