From 5bed4995b48baeb44620aa5a85fbaffebd681d83 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 17 Jan 2012 07:03:46 +0000 Subject: [PATCH] [NTOSKRNL] - Deallocate the process page directory when destroying its address space (removed in r48233 and now resurrected in a version compatible with ARM3) - Fixes leaking system pages on each process exit (868 MC_SYSTEM pages were allocated just sitting at the desktop on livecd without the patch, only 187 with the patch) svn path=/trunk/; revision=54988 --- reactos/ntoskrnl/include/internal/mm.h | 4 +- reactos/ntoskrnl/mm/i386/page.c | 58 ++++++++++++++++++++++++++ reactos/ntoskrnl/mm/marea.c | 2 + 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 22745c63748..09918a62af6 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -1503,9 +1503,9 @@ NTSTATUS NTAPI MmReleaseMmInfo(struct _EPROCESS *Process); -NTSTATUS +VOID NTAPI -Mmi386ReleaseMmInfo(struct _EPROCESS *Process); +MmDeleteProcessPageDirectory(struct _EPROCESS *Process); VOID NTAPI diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index a2ec088491e..219b9aa9edf 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -200,6 +200,64 @@ ProtectToPTE(ULONG flProtect) return(Attributes); } +static +VOID +MmDeletePageDirectoryEntry(ULONG PdeEntry) +{ + KIRQL OldIrql; + PMMPFN Page; + + Page = MiGetPfnEntry(PTE_TO_PFN(PdeEntry)); + + /* Check if this is a legacy allocation */ + if (MI_IS_ROS_PFN(Page)) + { + /* Free it using the legacy API */ + MmReleasePageMemoryConsumer(MC_SYSTEM, PTE_TO_PFN(PdeEntry)); + } + else + { + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + + /* Free it using the ARM3 API */ + MI_SET_PFN_DELETED(Page); + MiDecrementShareCount(Page, PTE_TO_PFN(PdeEntry)); + + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + } +} + +VOID +NTAPI +MmDeleteProcessPageDirectory(PEPROCESS Process) +{ + PULONG PageDir; + ULONG PdeOffset; + + /* Map the page directory in hyperspace */ + PageDir = MmCreateHyperspaceMapping(PTE_TO_PFN(Process->Pcb.DirectoryTableBase[0])); + + /* Loop the user land page directory */ + for (PdeOffset = 0; PdeOffset < ADDR_TO_PDE_OFFSET(MmSystemRangeStart); PdeOffset++) + { + /* Check if a valid PDE exists here */ + if (PageDir[PdeOffset] != 0) + { + /* Free the page that backs it */ + MmDeletePageDirectoryEntry(PageDir[PdeOffset]); + } + } + + /* Free the hyperspace mapping page (ARM3) */ + MmDeletePageDirectoryEntry(PageDir[ADDR_TO_PDE_OFFSET(HYPERSPACE)]); + + /* Delete the hyperspace mapping */ + MmDeleteHyperspaceMapping(PageDir); + + /* Free the PDE page itself (ARM3) */ + MmDeletePageDirectoryEntry(Process->Pcb.DirectoryTableBase[0]); +} + static PULONG MmGetPageTableForProcess(PEPROCESS Process, PVOID Address, BOOLEAN Create) { diff --git a/reactos/ntoskrnl/mm/marea.c b/reactos/ntoskrnl/mm/marea.c index 52e1a0f3b57..11d7649900a 100644 --- a/reactos/ntoskrnl/mm/marea.c +++ b/reactos/ntoskrnl/mm/marea.c @@ -1057,6 +1057,8 @@ MmDeleteProcessAddressSpace(PEPROCESS Process) } } + MmDeleteProcessPageDirectory(Process); + MmUnlockAddressSpace(&Process->Vm); DPRINT("Finished MmReleaseMmInfo()\n");