mirror of
https://github.com/reactos/reactos.git
synced 2025-07-31 19:21:38 +00:00
[NTOS/MM]
- Implement MiResolvePageFileFault - Add a debug print showing how many ARM3 pages could be used by the balancer svn path=/trunk/; revision=63821
This commit is contained in:
parent
3cfcb20668
commit
9aec0d47eb
4 changed files with 171 additions and 29 deletions
|
@ -648,6 +648,13 @@ VOID
|
|||
NTAPI
|
||||
MmShowOutOfSpaceMessagePagingFile(VOID);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiReadPageFile(
|
||||
_In_ PFN_NUMBER Page,
|
||||
_In_ ULONG PageFileIndex,
|
||||
_In_ ULONG_PTR PageFileOffset);
|
||||
|
||||
/* process.c ****************************************************************/
|
||||
|
||||
NTSTATUS
|
||||
|
|
|
@ -808,6 +808,96 @@ MiCompleteProtoPteFault(IN BOOLEAN StoreInstruction,
|
|||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -846,8 +936,19 @@ MiResolveTransitionFault(IN PVOID FaultingAddress,
|
|||
/* 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,6 +1426,30 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
|||
/* 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);
|
||||
|
@ -1333,19 +1458,14 @@ MiDispatchFault(IN BOOLEAN StoreInstruction,
|
|||
|
||||
//
|
||||
// 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.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);
|
||||
ASSERT(TempPte.u.Long != 0);
|
||||
|
||||
//
|
||||
// If we got this far, the PTE can only be a demand zero PTE, which is what
|
||||
|
|
|
@ -355,6 +355,9 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait,
|
|||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
extern MMPFNLIST MmModifiedPageListByColor[];
|
||||
|
||||
VOID NTAPI
|
||||
MiBalancerThread(PVOID Unused)
|
||||
{
|
||||
|
@ -424,6 +427,9 @@ MiBalancerThread(PVOID Unused)
|
|||
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
|
||||
{
|
||||
|
|
|
@ -48,8 +48,8 @@ typedef struct _PAGINGFILE
|
|||
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 @@ RETRIEVEL_DESCRIPTOR_LIST, *PRETRIEVEL_DESCRIPTOR_LIST;
|
|||
|
||||
#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 PPAGINGFILE PagingFileList[MAX_PAGING_FILES];
|
|||
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 @@ MmIsFileObjectAPagingFile(PFILE_OBJECT FileObject)
|
|||
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 @@ MmWriteToSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
|
|||
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;
|
||||
PPAGINGFILE PagingFile;
|
||||
|
||||
DPRINT("MmReadFromSwapPage\n");
|
||||
DPRINT("MiReadSwapFile\n");
|
||||
|
||||
if (SwapEntry == 0)
|
||||
if (PageFileOffset == 0)
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
return(STATUS_UNSUCCESSFUL);
|
||||
}
|
||||
|
||||
i = FILE_FROM_ENTRY(SwapEntry);
|
||||
offset = OFFSET_FROM_ENTRY(SwapEntry);
|
||||
ASSERT(PageFileIndex < MAX_PAGING_FILES);
|
||||
|
||||
if (PagingFileList[i]->FileObject == NULL ||
|
||||
PagingFileList[i]->FileObject->DeviceObject == NULL)
|
||||
PagingFile = PagingFileList[PageFileIndex];
|
||||
|
||||
if (PagingFile->FileObject == NULL || PagingFile->FileObject->DeviceObject == NULL)
|
||||
{
|
||||
DPRINT1("Bad paging file 0x%.8X\n", SwapEntry);
|
||||
DPRINT1("Bad paging file %u\n", PageFileIndex);
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
|
||||
|
@ -310,11 +319,11 @@ MmReadFromSwapPage(SWAPENTRY SwapEntry, PFN_NUMBER Page)
|
|||
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 @@ MmInitPagingFile(VOID)
|
|||
{
|
||||
PagingFileList[i] = NULL;
|
||||
}
|
||||
MiPagingFileCount = 0;
|
||||
MmNumberOfPagingFiles = 0;
|
||||
}
|
||||
|
||||
static ULONG
|
||||
|
@ -498,7 +507,7 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
|
|||
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 @@ NtCreatePagingFile(IN PUNICODE_STRING FileName,
|
|||
}
|
||||
}
|
||||
MiFreeSwapPages = MiFreeSwapPages + PagingFile->FreePages;
|
||||
MiPagingFileCount++;
|
||||
MmNumberOfPagingFiles++;
|
||||
KeReleaseSpinLock(&PagingFileListLock, oldIrql);
|
||||
|
||||
ZwClose(FileHandle);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue