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=…
==============================================================================
--- 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=…
==============================================================================
--- 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?re…
==============================================================================
--- 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=55…
==============================================================================
--- 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=…
==============================================================================
--- 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);