Author: jgardou
Date: Wed Aug 6 21:53:09 2014
New Revision: 63821
URL:
http://svn.reactos.org/svn/reactos?rev=63821&view=rev
Log:
[NTOS/MM]
- Implement MiResolvePageFileFault
- Add a debug print showing how many ARM3 pages could be used by the balancer
Modified:
trunk/reactos/ntoskrnl/include/internal/mm.h
trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
trunk/reactos/ntoskrnl/mm/balance.c
trunk/reactos/ntoskrnl/mm/pagefile.c
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Wed Aug 6 21:53:09 2014
@@ -648,6 +648,13 @@
NTAPI
MmShowOutOfSpaceMessagePagingFile(VOID);
+NTSTATUS
+NTAPI
+MiReadPageFile(
+ _In_ PFN_NUMBER Page,
+ _In_ ULONG PageFileIndex,
+ _In_ ULONG_PTR PageFileOffset);
+
/* process.c ****************************************************************/
NTSTATUS
Modified: trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/pagfault.…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/pagfault.c [iso-8859-1] Wed Aug 6 21:53:09 2014
@@ -810,6 +810,96 @@
NTSTATUS
NTAPI
+MiResolvePageFileFault(_In_ BOOLEAN StoreInstruction,
+ _In_ PVOID FaultingAddress,
+ _In_ PMMPTE PointerPte,
+ _In_ PEPROCESS CurrentProcess,
+ _Inout_ KIRQL *OldIrql)
+{
+ ULONG Color;
+ PFN_NUMBER Page;
+ NTSTATUS Status;
+ MMPTE TempPte = *PointerPte;
+ KEVENT Event;
+ PMMPFN Pfn1;
+ ULONG PageFileIndex = TempPte.u.Soft.PageFileLow;
+ ULONG_PTR PageFileOffset = TempPte.u.Soft.PageFileHigh;
+
+ /* Things we don't support yet */
+ ASSERT(CurrentProcess > HYDRA_PROCESS);
+ ASSERT(*OldIrql != MM_NOIRQL);
+
+ /* We must hold the PFN lock */
+ ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
+
+ /* Some sanity checks */
+ ASSERT(TempPte.u.Hard.Valid == 0);
+ ASSERT(TempPte.u.Soft.PageFileHigh != 0);
+ ASSERT(TempPte.u.Soft.PageFileHigh != MI_PTE_LOOKUP_NEEDED);
+
+ /* Get any page, it will be overwritten */
+ Color = MI_GET_NEXT_PROCESS_COLOR(CurrentProcess);
+ Page = MiRemoveAnyPage(Color);
+
+ /* Initialize this PFN */
+ MiInitializePfn(Page, PointerPte, StoreInstruction);
+
+ /* Sets the PFN as being in IO operation */
+ Pfn1 = MI_PFN_ELEMENT(Page);
+ ASSERT(Pfn1->u1.Event == NULL);
+ ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
+ ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
+
+ KeInitializeEvent(&Event, NotificationEvent, FALSE);
+ Pfn1->u1.Event = &Event;
+ Pfn1->u3.e1.ReadInProgress = 1;
+
+ /* We must write the PTE now as the PFN lock will be released while performing the IO
operation */
+ TempPte.u.Soft.Transition = 1;
+ TempPte.u.Soft.PageFileLow = 0;
+ TempPte.u.Soft.Prototype = 0;
+ TempPte.u.Trans.PageFrameNumber = Page;
+
+ MI_WRITE_INVALID_PTE(PointerPte, TempPte);
+
+ /* Release the PFN lock while we proceed */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, *OldIrql);
+
+ /* Do the paging IO */
+ Status = MiReadPageFile(Page, PageFileIndex, PageFileOffset);
+
+ /* Lock the PFN database again */
+ *OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Nobody should have changed that while we were not looking */
+ ASSERT(Pfn1->u1.Event == &Event);
+ ASSERT(Pfn1->u3.e1.ReadInProgress == 1);
+ ASSERT(Pfn1->u3.e1.WriteInProgress == 0);
+
+ if (!NT_SUCCESS(Status))
+ {
+ /* Malheur! */
+ ASSERT(FALSE);
+ Pfn1->u4.InPageError = 1;
+ Pfn1->u1.ReadStatus = Status;
+ }
+
+ /* This is now a nice and normal PFN */
+ Pfn1->u1.Event = NULL;
+ Pfn1->u3.e1.ReadInProgress = 0;
+
+ /* And the PTE can finally be valid */
+ MI_MAKE_HARDWARE_PTE(&TempPte, PointerPte, TempPte.u.Trans.Protection, Page);
+ MI_WRITE_VALID_PTE(PointerPte, TempPte);
+
+ /* Waiters gonna wait */
+ KeSetEvent(&Event, IO_NO_INCREMENT, FALSE);
+
+ return Status;
+}
+
+NTSTATUS
+NTAPI
MiResolveTransitionFault(IN PVOID FaultingAddress,
IN PMMPTE PointerPte,
IN PEPROCESS CurrentProcess,
@@ -846,8 +936,19 @@
/* This is from ARM3 -- Windows normally handles this here */
ASSERT(Pfn1->u4.InPageError == 0);
- /* Not supported in ARM3 */
- ASSERT(Pfn1->u3.e1.ReadInProgress == 0);
+ /* See if we should wait before terminating the fault */
+ if (Pfn1->u3.e1.ReadInProgress == 1)
+ {
+ DPRINT1("The page is currently being read!\n");
+ ASSERT(Pfn1->u1.Event != NULL);
+ *InPageBlock = Pfn1->u1.Event;
+ if (PointerPte == Pfn1->PteAddress)
+ {
+ DPRINT1("And this if for this particular PTE.\n");
+ /* The PTE will be made valid by the thread serving the fault */
+ return STATUS_SUCCESS; // FIXME: Maybe something more descriptive
+ }
+ }
/* Windows checks there's some free pages and this isn't an in-page error */
ASSERT(MmAvailablePages > 0);
@@ -1325,27 +1426,46 @@
/* And now release the lock and leave*/
KeReleaseQueuedSpinLock(LockQueuePfnLock, LockIrql);
+ if (InPageBlock != NULL)
+ {
+ /* The page is being paged in by another process */
+ KeWaitForSingleObject(InPageBlock, WrPageIn, KernelMode, FALSE, NULL);
+ }
+
ASSERT(OldIrql == KeGetCurrentIrql());
ASSERT(OldIrql <= APC_LEVEL);
ASSERT(KeAreAllApcsDisabled() == TRUE);
return Status;
}
+ /* Should we page the data back in ? */
+ if (TempPte.u.Soft.PageFileHigh != 0)
+ {
+ /* Lock the PFN database */
+ LockIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Resolve */
+ Status = MiResolvePageFileFault(StoreInstruction, Address, PointerPte, Process,
&LockIrql);
+
+ /* And now release the lock and leave*/
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, LockIrql);
+
+ ASSERT(OldIrql == KeGetCurrentIrql());
+ ASSERT(OldIrql <= APC_LEVEL);
+ ASSERT(KeAreAllApcsDisabled() == TRUE);
+ return Status;
+ }
+
//
// The PTE must be invalid but not completely empty. It must also not be a
- // prototype or transition PTE as those scenarii should've been handled above.
+ // prototype a transition or a paged-out PTE as those scenarii should've been
handled above.
// These are all Windows checks
//
ASSERT(TempPte.u.Hard.Valid == 0);
ASSERT(TempPte.u.Soft.Prototype == 0);
ASSERT(TempPte.u.Soft.Transition == 0);
+ ASSERT(TempPte.u.Soft.PageFileHigh == 0);
ASSERT(TempPte.u.Long != 0);
-
- //
- // No page file software PTEs in ARM3 yet, so this must be a
- // demand zero page. This is a ReactOS check.
- //
- ASSERT(TempPte.u.Soft.PageFileHigh == 0);
//
// If we got this far, the PTE can only be a demand zero PTE, which is what
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] Wed Aug 6 21:53:09 2014
@@ -354,6 +354,9 @@
return(STATUS_SUCCESS);
}
+
+
+extern MMPFNLIST MmModifiedPageListByColor[];
VOID NTAPI
MiBalancerThread(PVOID Unused)
@@ -424,6 +427,9 @@
KeBugCheck(NO_PAGES_AVAILABLE);
}
} while (InitialTarget != 0);
+
+ if (MmModifiedPageListByColor[0].Total != 0)
+ DPRINT1("There are %u pages ready to be paged out in the modified
list.\n", MmModifiedPageListByColor[0].Total);
}
else
{
Modified: trunk/reactos/ntoskrnl/mm/pagefile.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/pagefile.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/pagefile.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/pagefile.c [iso-8859-1] Wed Aug 6 21:53:09 2014
@@ -48,8 +48,8 @@
PFILE_OBJECT FileObject;
LARGE_INTEGER MaximumSize;
LARGE_INTEGER CurrentSize;
- ULONG FreePages;
- ULONG UsedPages;
+ PFN_NUMBER FreePages;
+ PFN_NUMBER UsedPages;
PULONG AllocMap;
KSPIN_LOCK AllocMapLock;
ULONG AllocMapSize;
@@ -68,7 +68,7 @@
#define PAIRS_PER_RUN (1024)
-#define MAX_PAGING_FILES (32)
+#define MAX_PAGING_FILES (16)
/* List of paging files, both used and free */
static PPAGINGFILE PagingFileList[MAX_PAGING_FILES];
@@ -77,7 +77,6 @@
static KSPIN_LOCK PagingFileListLock;
/* Number of paging files */
-static ULONG MiPagingFileCount;
ULONG MmNumberOfPagingFiles;
/* Number of pages that are available for swapping */
@@ -140,7 +139,7 @@
ULONG i;
/* Loop through all the paging files */
- for (i = 0; i < MiPagingFileCount; i++)
+ for (i = 0; i < MmNumberOfPagingFiles; i++)
{
/* Check if this is one of them */
if (PagingFileList[i]->FileObject == FileObject) return TRUE;
@@ -275,34 +274,44 @@
return(Status);
}
+
NTSTATUS
NTAPI
MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
{
- ULONG i;
- ULONG_PTR offset;
+ return MiReadPageFile(Page, FILE_FROM_ENTRY(SwapEntry), OFFSET_FROM_ENTRY(SwapEntry));
+}
+
+NTSTATUS
+NTAPI
+MiReadPageFile(
+ _In_ PFN_NUMBER Page,
+ _In_ ULONG PageFileIndex,
+ _In_ ULONG_PTR PageFileOffset)
+{
LARGE_INTEGER file_offset;
IO_STATUS_BLOCK Iosb;
NTSTATUS Status;
KEVENT Event;
UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
PMDL Mdl = (PMDL)MdlBase;
-
- DPRINT("MmReadFromSwapPage\n");
-
- if (SwapEntry == 0)
+ PPAGINGFILE PagingFile;
+
+ DPRINT("MiReadSwapFile\n");
+
+ if (PageFileOffset == 0)
{
KeBugCheck(MEMORY_MANAGEMENT);
return(STATUS_UNSUCCESSFUL);
}
- i = FILE_FROM_ENTRY(SwapEntry);
- offset = OFFSET_FROM_ENTRY(SwapEntry);
-
- if (PagingFileList[i]->FileObject == NULL ||
- PagingFileList[i]->FileObject->DeviceObject == NULL)
- {
- DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
+ ASSERT(PageFileIndex < MAX_PAGING_FILES);
+
+ PagingFile = PagingFileList[PageFileIndex];
+
+ if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject ==
NULL)
+ {
+ DPRINT1("Bad paging file %u\n", PageFileIndex);
KeBugCheck(MEMORY_MANAGEMENT);
}
@@ -310,11 +319,11 @@
MmBuildMdlFromPages(Mdl, &Page);
Mdl->MdlFlags |= MDL_PAGES_LOCKED;
- file_offset.QuadPart = offset * PAGE_SIZE;
- file_offset = MmGetOffsetPageFile(PagingFileList[i]->RetrievalPointers,
file_offset);
+ file_offset.QuadPart = PageFileOffset * PAGE_SIZE;
+ file_offset = MmGetOffsetPageFile(PagingFile->RetrievalPointers, file_offset);
KeInitializeEvent(&Event, NotificationEvent, FALSE);
- Status = IoPageRead(PagingFileList[i]->FileObject,
+ Status = IoPageRead(PagingFile->FileObject,
Mdl,
&file_offset,
&Event,
@@ -348,7 +357,7 @@
{
PagingFileList[i] = NULL;
}
- MiPagingFileCount = 0;
+ MmNumberOfPagingFiles = 0;
}
static ULONG
@@ -498,7 +507,7 @@
DPRINT("NtCreatePagingFile(FileName %wZ, InitialSize %I64d)\n",
FileName, InitialSize->QuadPart);
- if (MiPagingFileCount >= MAX_PAGING_FILES)
+ if (MmNumberOfPagingFiles >= MAX_PAGING_FILES)
{
return(STATUS_TOO_MANY_PAGING_FILES);
}
@@ -800,7 +809,7 @@
}
}
MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages;
- MiPagingFileCount++;
+ MmNumberOfPagingFiles++;
KeReleaseSpinLock(&PagingFileListLock, oldIrql);
ZwClose(FileHandle);