Author: arty
Date: Fri Jan 8 11:26:30 2010
New Revision: 44995
URL:
http://svn.reactos.org/svn/reactos?rev=44995&view=rev
Log:
Keep pages referenced while paging out so we can follow the LRU chain in all cases.
Explicitly handle STATUS_MM_RESTART_OPERATION like we used to.
My previous code for pulling in a page, then faulting it into the address space
wasn't correct; we take the easier route of pretending we're starting fresh once
we've pulled the page into the section.
MmDeleteSectionAssociation is now necessary since we may not hold the (quite) last
reference.
Modified:
branches/arty-newcc/ntoskrnl/include/internal/mm.h
branches/arty-newcc/ntoskrnl/mm/balance.c
branches/arty-newcc/ntoskrnl/mm/freelist.c
branches/arty-newcc/ntoskrnl/mm/mmfault.c
branches/arty-newcc/ntoskrnl/mm/rmap.c
branches/arty-newcc/ntoskrnl/mm/section/data.c
branches/arty-newcc/ntoskrnl/mm/section/fault.c
branches/arty-newcc/ntoskrnl/mm/section/pagefile.c
Modified: branches/arty-newcc/ntoskrnl/include/internal/mm.h
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/include/int…
==============================================================================
--- branches/arty-newcc/ntoskrnl/include/internal/mm.h [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/include/internal/mm.h [iso-8859-1] Fri Jan 8 11:26:30
2010
@@ -2207,7 +2207,7 @@
_MmTryToLockAddressSpace(IN PMMSUPPORT AddressSpace, const char *file, int line)
{
BOOLEAN Result = KeTryToAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace,
EPROCESS, Vm)->AddressCreationLock);
- DbgPrint("(%s:%d) Try Lock Address Space %x -> %s\n", file, line,
AddressSpace, Result ? "true" : "false");
+ //DbgPrint("(%s:%d) Try Lock Address Space %x -> %s\n", file, line,
AddressSpace, Result ? "true" : "false");
return Result;
}
Modified: branches/arty-newcc/ntoskrnl/mm/balance.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/balance.…
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/balance.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/balance.c [iso-8859-1] Fri Jan 8 11:26:30 2010
@@ -33,7 +33,7 @@
BOOLEAN MiBalancerInitialized = FALSE;
MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM];
-/*static*/ ULONG MiMinimumAvailablePages = 0x3000;
+/*static*/ ULONG MiMinimumAvailablePages = 128;
static ULONG MiNrTotalPages;
static LIST_ENTRY AllocationListHead;
static KSPIN_LOCK AllocationListLock;
@@ -137,21 +137,19 @@
MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages)
{
PFN_TYPE CurrentPage;
- PFN_TYPE NextPage;
NTSTATUS Status;
(*NrFreedPages) = 0;
DPRINT("Trimming user memory (want %d)\n", Target);
-
+
+ // Current page is referenced
CurrentPage = MmGetLRUFirstUserPage();
while (CurrentPage != 0 && Target > 0)
{
- //DPRINT("Trying page %x\n", CurrentPage);
- NextPage = MmGetLRUNextUserPage(CurrentPage);
Status = MmPageOutPhysicalAddress(CurrentPage);
- //DPRINT("Status: %x\n", Status);
if (NT_SUCCESS(Status))
{
+ MmRemoveLRUUserPage(CurrentPage);
Target--;
(*NrFreedPages)++;
}
@@ -160,9 +158,12 @@
MmRemoveLRUUserPage(CurrentPage);
MmInsertLRULastUserPage(CurrentPage);
}
-
- CurrentPage = NextPage;
+
+ // Reference is updated
+ CurrentPage = MmGetLRUNextUserPage(CurrentPage);
}
+ if (CurrentPage)
+ MmDereferencePage(CurrentPage); // Dereference matches MmGetLRUFirst/Next
DPRINT("Done\n");
return(STATUS_SUCCESS);
}
Modified: branches/arty-newcc/ntoskrnl/mm/freelist.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/freelist…
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/freelist.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/freelist.c [iso-8859-1] Fri Jan 8 11:26:30 2010
@@ -107,6 +107,7 @@
}
PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
ASSERT_PFN(PageDescriptor);
+ MmReferencePage(PageDescriptor - MmPfnDatabase);
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
return PageDescriptor - MmPfnDatabase;
}
@@ -148,7 +149,9 @@
return 0;
}
PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
+ MmReferencePage(PageDescriptor - MmPfnDatabase);
KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+ MmDereferencePage(PreviousPfn);
return PageDescriptor - MmPfnDatabase;
}
@@ -156,7 +159,10 @@
NTAPI
MmRemoveLRUUserPage(PFN_TYPE Page)
{
+ KIRQL oldIrql;
+ oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
RemoveEntryList(&MiGetPfnEntry(Page)->ListEntry);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
}
PFN_NUMBER
Modified: branches/arty-newcc/ntoskrnl/mm/mmfault.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/mmfault.…
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/mmfault.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/mmfault.c [iso-8859-1] Fri Jan 8 11:26:30 2010
@@ -172,6 +172,11 @@
ASSERT(FALSE);
DPRINT("Restarting fault %x\n", Address);
Status = STATUS_MM_RESTART_OPERATION;
+ }
+ else if (Status == STATUS_MM_RESTART_OPERATION)
+ {
+ // Clean slate
+ RtlZeroMemory(&Resources, sizeof(Resources));
}
else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
{
@@ -355,6 +360,11 @@
DPRINT("Done waiting for %x\n", Address);
Status = STATUS_MM_RESTART_OPERATION;
}
+ else if (Status == STATUS_MM_RESTART_OPERATION)
+ {
+ // Clean slate
+ RtlZeroMemory(&Resources, sizeof(Resources));
+ }
else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
{
if (Thread->ActiveFaultCount > 1)
@@ -413,7 +423,8 @@
PETHREAD Thread;
PMMSUPPORT AddressSpace;
NTSTATUS Status;
-
+
+ Address &= ~(PAGE_SIZE - 1);
DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
Thread = PsGetCurrentThread();
@@ -461,6 +472,8 @@
IN PVOID TrapInformation)
{
PMEMORY_AREA MemoryArea;
+
+ Address = (PVOID)(((ULONG_PTR)Address) & ~(PAGE_SIZE - 1));
/* Cute little hack for ROS */
if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart)
Modified: branches/arty-newcc/ntoskrnl/mm/rmap.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/rmap.c?r…
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/rmap.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/rmap.c [iso-8859-1] Fri Jan 8 11:26:30 2010
@@ -349,7 +349,7 @@
if (MmGetRmapListHeadPage(Page))
{
- DPRINT1("Page %x was re-acquired while we were evicting it\n", Page);
+ DPRINT("Page %x was re-acquired while we were evicting it\n", Page);
MmLockSectionSegment(Segment);
MiSetPageEntrySectionSegment(Segment, &FileOffset, Dirty ?
DIRTY_SSE(MAKE_PFN_SSE(SectionPage)) : MAKE_PFN_SSE(SectionPage));
MmUnlockSectionSegment(Segment);
@@ -366,7 +366,7 @@
if (!Evicted && SectionPage)
{
- DPRINT1
+ DPRINT
("Failed to page out, replacing %x at %x in segment %x\n",
SectionPage, FileOffset.LowPart, Segment);
MmLockSectionSegment(Segment);
Modified: branches/arty-newcc/ntoskrnl/mm/section/data.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/section/…
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/section/data.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/section/data.c [iso-8859-1] Fri Jan 8 11:26:30 2010
@@ -1174,7 +1174,7 @@
MiWriteBackPage(FileObject, FileOffset, PAGE_SIZE, OldPage);
DPRINT("Dereference page %x\n", OldPage);
}
- ASSERT(MmGetReferenceCountPage(OldPage) == 1);
+ MmDeleteSectionAssociation(OldPage);
MmDereferencePage(OldPage);
DPRINT("Done\n");
}
Modified: branches/arty-newcc/ntoskrnl/mm/section/fault.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/section/…
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/section/fault.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/section/fault.c [iso-8859-1] Fri Jan 8 11:26:30 2010
@@ -97,6 +97,8 @@
&MemoryArea->Data.SectionData.RegionListHead,
Address, NULL);
+ ASSERT(Region);
+
TotalOffset.QuadPart += MemoryArea->Data.SectionData.ViewOffset.QuadPart;
FileOffset = TotalOffset;
@@ -145,27 +147,41 @@
if (Required->State && Required->Page[0])
{
- DPRINT("Have file and page, set page in section @ %x\n",
TotalOffset.LowPart);
- Status = MiSetPageEntrySectionSegment
- (Segment, &TotalOffset, Entry = MAKE_PFN_SSE(Required->Page[0]));
- if (NT_SUCCESS(Status))
- {
- MmReferencePage(Required->Page[0]);
+ DPRINT("Have file and page, set page %x in section @ %x\n",
Required->Page[0], TotalOffset.LowPart);
+ if (Required->State & 2)
+ {
+ Status = MiSetPageEntrySectionSegment
+ (Segment, &TotalOffset, Entry = MAKE_PFN_SSE(Required->Page[0]));
+ if (!NT_SUCCESS(Status))
+ {
+ MmDereferencePage(Required->Page[0]);
+ }
+ MmUnlockSectionSegment(Segment);
+ DPRINT("XXX Set Event %x\n", Status);
+ KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE);
+ DPRINT("Status %x\n", Status);
+ return STATUS_MM_RESTART_OPERATION;
+ }
+ else
+ {
+ DPRINT("Set %x in address space @ %x\n", Required->Page[0], Address);
Status = MmCreateVirtualMapping(Process, Address, Attributes, Required->Page, 1);
if (NT_SUCCESS(Status))
{
MmInsertRmap(Required->Page[0], Process, Address);
+ if (Locked) MmLockPage(Required->Page[0]);
}
else
{
+ // Drop the reference for our address space ...
MmDereferencePage(Required->Page[0]);
}
- }
- MmUnlockSectionSegment(Segment);
- DPRINT("XXX Set Event %x\n", Status);
- KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE);
- DPRINT("Status %x\n", Status);
- return Status;
+ MmUnlockSectionSegment(Segment);
+ DPRINT("XXX Set Event %x\n", Status);
+ KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE);
+ DPRINT("Status %x\n", Status);
+ return Status;
+ }
}
else if (MmIsPageSwapEntry(Process, Address))
{
@@ -180,8 +196,7 @@
else
{
DPRINT("Swap in\n");
- MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
- Required->State = 7;
+ Required->State = 1;
Required->Consumer = Consumer;
Required->SwapEntry = SwapEntry;
Required->DoAcquisition = MiSwapInPage;
@@ -201,9 +216,7 @@
else
{
DPRINT("Swap in\n");
- MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
- MiSetPageEntrySectionSegment(Segment, &TotalOffset,
MAKE_SWAP_SSE(MM_WAIT_ENTRY));
- Required->State = 7;
+ Required->State = 3;
Required->Consumer = Consumer;
Required->SwapEntry = SwapEntry;
Required->DoAcquisition = MiSwapInPage;
@@ -220,6 +233,7 @@
if (NT_SUCCESS(Status))
{
MmInsertRmap(Page, Process, Address);
+ if (Locked) MmLockPage(Required->Page[0]);
Required->Page[0] = 0;
}
DPRINT("XXX Set Event %x\n", Status);
@@ -241,7 +255,7 @@
(IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA))))
{
DPRINT("Read from file %08x\n", FileOffset.LowPart);
- Required->State = 1;
+ Required->State = 3;
Required->Context = Section->FileObject;
Required->Consumer = Consumer;
Required->FileOffset = FileOffset;
@@ -252,7 +266,7 @@
else
{
DPRINT("Get Page\n");
- Required->State = 1;
+ Required->State = 3;
Required->Amount = 1;
Required->Consumer = Consumer;
Required->DoAcquisition = MiGetOnePage;
@@ -338,45 +352,47 @@
if (Required->Page[0] && Required->State)
{
- Page = Required->Page[0];
-
DPRINT("Have Page: %x %d\n", Page, Required->State);
- if (Required->State & 1)
+ if (Required->State & 2)
{
DPRINT("Set in section @ %x\n", Offset.LowPart);
Status = MiSetPageEntrySectionSegment
- (Segment, &Offset, MAKE_PFN_SSE(Page));
- }
-
- if (Required->State & 2)
- {
- DPRINT("Set in address space @ %x\n", Address);
- Status = MmCreateVirtualMapping
- (Process, Address, Attributes, &Page, 1);
+ (Segment, &Offset, Entry = MAKE_PFN_SSE(Required->Page[0]));
+ if (!NT_SUCCESS(Status))
+ {
+ MmDereferencePage(Required->Page[0]);
+ }
+ MmUnlockSectionSegment(Segment);
+ DPRINT("XXX Set Event %x\n", Status);
+ KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE);
+ DPRINT("Status %x\n", Status);
+ return STATUS_MM_RESTART_OPERATION;
+ }
+ else
+ {
+ DPRINT("Set %x in address space @ %x\n", Required->Page[0], Address);
+ Status = MmCreateVirtualMapping(Process, Address, Attributes, Required->Page, 1);
if (NT_SUCCESS(Status))
{
- MmInsertRmap(Page, Process, Address);
- if (Locked) MmLockPage(Page);
+ MmInsertRmap(Required->Page[0], Process, Address);
+ if (Locked) MmLockPage(Required->Page[0]);
}
- }
-
- if (Required->State & 4)
- {
- DPRINT("Take a reference\n");
- Status = STATUS_SUCCESS;
- MmReferencePage(Page);
- }
-
- MmUnlockSectionSegment(Segment);
- DPRINT("XXX Set Event %x\n", Status);
- KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE);
- DPRINT("Done: %x\n", Status);
- return Status;
+ else
+ {
+ // Drop the reference for our address space
+ MmDereferencePage(Required->Page[0]);
+ }
+ MmUnlockSectionSegment(Segment);
+ DPRINT("XXX Set Event %x\n", Status);
+ KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE);
+ DPRINT("Done: %x\n", Status);
+ return Status;
+ }
}
if (Entry == 0 && !HasSwapEntry && Offset.QuadPart <
PAGE_ROUND_UP(Segment->RawLength.QuadPart))
{
- Required->State = 7;
+ Required->State = 3;
Required->Context = Section->FileObject;
Required->Consumer = MC_USER;
Required->FileOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
@@ -398,8 +414,7 @@
* Must be private page we have swapped out.
*/
DPRINT("Private swapped out page\n");
- MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
- Required->State = 2;
+ Required->State = 1;
Required->Consumer = MC_USER;
Required->DoAcquisition = MiSwapInPage;
MmUnlockSectionSegment(Segment);
@@ -414,10 +429,9 @@
else if (IS_SWAP_FROM_SSE(Entry))
{
DPRINT("Swap in section page\n");
- Required->State = 7;
+ Required->State = 3;
Required->Consumer = MC_USER;
MmGetPageFileMapping(Process, (PVOID)PAddress, &Required->SwapEntry);
- MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
Required->DoAcquisition = MiSwapInPage;
MmUnlockSectionSegment(Segment);
return STATUS_MORE_PROCESSING_REQUIRED;
@@ -430,7 +444,7 @@
Offset.QuadPart >= PAGE_ROUND_UP(Segment->RawLength.QuadPart)))
{
DPRINT("BSS Page\n");
- Required->State = 2;
+ Required->State = 1;
Required->Amount = 1;
Required->Consumer = MC_USER;
Required->DoAcquisition = MiGetOnePage;
@@ -835,7 +849,6 @@
}
DPRINT("MiWriteSwapPage (%x -> %x)\n", OurPage, Required->SwapEntry);
Required->DoAcquisition = MiWriteSwapPage;
- MmCreatePageFileMapping(Process, Address, MM_WAIT_ENTRY);
MmUnlockSectionSegment(Segment);
return STATUS_MORE_PROCESSING_REQUIRED;
}
Modified: branches/arty-newcc/ntoskrnl/mm/section/pagefile.c
URL:
http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/section/…
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/section/pagefile.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/section/pagefile.c [iso-8859-1] Fri Jan 8 11:26:30
2010
@@ -176,7 +176,7 @@
Status = STATUS_PAGEFILE_QUOTA;
else
{
- DPRINT("Writing to swap page\n");
+ DPRINT1("Writing to swap %x page %x\n", Swap, Page);
Status = MmWriteToSwapPage(Swap, Page);
}
@@ -207,7 +207,7 @@
if (WritePage)
{
- DPRINT("Segment %x FileObject %x Offset %x\n", Segment,
Segment->FileObject, FileOffset->LowPart);
+ DPRINT1("MiWriteBackPage(Segment %x FileObject %x Offset %x)\n", Segment,
Segment->FileObject, FileOffset->LowPart);
Status = MiWriteBackPage(Segment->FileObject, FileOffset, PAGE_SIZE, Page);
}
@@ -215,6 +215,7 @@
{
DPRINT("Removing page %x for real\n", Page);
MmSetSavedSwapEntryPage(Page, 0);
+ MmDeleteSectionAssociation(Page);
MmDereferencePage(Page);
}