Author: arty Date: Fri Nov 27 02:03:24 2009 New Revision: 44291
URL: http://svn.reactos.org/svn/reactos?rev=44291&view=rev Log: Revert my recent traffic for now. This needs to be approached differently. I'm going in the wrong direction in complexity terms.
Modified: branches/arty-newcc/ntoskrnl/cache/fssup.c branches/arty-newcc/ntoskrnl/cache/lazyrite.c branches/arty-newcc/ntoskrnl/include/internal/newmm.h branches/arty-newcc/ntoskrnl/io/iomgr/device.c branches/arty-newcc/ntoskrnl/io/iomgr/iofunc.c branches/arty-newcc/ntoskrnl/io/iomgr/rawfs.c branches/arty-newcc/ntoskrnl/mm/anonmem.c branches/arty-newcc/ntoskrnl/mm/balance.c branches/arty-newcc/ntoskrnl/mm/freelist.c branches/arty-newcc/ntoskrnl/mm/mpw.c branches/arty-newcc/ntoskrnl/mm/pageop.c branches/arty-newcc/ntoskrnl/mm/rmap.c branches/arty-newcc/ntoskrnl/mm/section/data.c branches/arty-newcc/ntoskrnl/mm/section/image.c branches/arty-newcc/ntoskrnl/mm/section/io.c branches/arty-newcc/ntoskrnl/mm/section/pagefile.c
Modified: branches/arty-newcc/ntoskrnl/cache/fssup.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/cache/fssup.... ============================================================================== --- branches/arty-newcc/ntoskrnl/cache/fssup.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/cache/fssup.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -17,7 +17,12 @@
PFSN_PREFETCHER_GLOBALS CcPfGlobals; extern LONG CcOutstandingDeletes; +extern KEVENT CcpLazyWriteEvent; extern KEVENT CcFinalizeEvent; +extern VOID NTAPI CcpUnmapThread(PVOID Unused); +extern VOID NTAPI CcpLazyWriteThread(PVOID Unused); +HANDLE CcUnmapThreadHandle, CcLazyWriteThreadHandle; +CLIENT_ID CcUnmapThreadId, CcLazyWriteThreadId;
typedef struct _NOCC_PRIVATE_CACHE_MAP { @@ -43,6 +48,7 @@
KeInitializeEvent(&CcDeleteEvent, SynchronizationEvent, FALSE); KeInitializeEvent(&CcFinalizeEvent, SynchronizationEvent, FALSE); + KeInitializeEvent(&CcpLazyWriteEvent, SynchronizationEvent, FALSE);
CcCacheBitmap->Buffer = ((PULONG)&CcCacheBitmap[1]); CcCacheBitmap->SizeOfBitMap = ROUND_UP(CACHE_NUM_SECTIONS, 32);
Modified: branches/arty-newcc/ntoskrnl/cache/lazyrite.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/cache/lazyri... ============================================================================== --- branches/arty-newcc/ntoskrnl/cache/lazyrite.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/cache/lazyrite.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -14,15 +14,21 @@
/* GLOBALS ********************************************************************/
-extern KEVENT MpwCompleteEvent; +KEVENT CcpLazyWriteEvent;
/* FUNCTIONS ******************************************************************/ + +VOID NTAPI +CcpLazyWriteThread(PVOID Unused) +{ + /* Not implemented */ +}
NTSTATUS NTAPI CcWaitForCurrentLazyWriterActivity(VOID) { - KeWaitForSingleObject(&MpwCompleteEvent, Executive, KernelMode, FALSE, NULL); + //KeWaitForSingleObject(&CcpLazyWriteEvent, Executive, KernelMode, FALSE, NULL); return STATUS_SUCCESS; }
Modified: branches/arty-newcc/ntoskrnl/include/internal/newmm.h URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/include/inte... ============================================================================== --- branches/arty-newcc/ntoskrnl/include/internal/newmm.h [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/include/internal/newmm.h [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -260,7 +260,7 @@
typedef struct _MM_SECTION_SEGMENT { - KGUARDED_MUTEX Lock; /* lock which protects the page directory */ + FAST_MUTEX Lock; /* lock which protects the page directory */ PFILE_OBJECT FileObject; ULARGE_INTEGER RawLength; /* length of the segment which is part of the mapped file */ ULARGE_INTEGER Length; /* absolute length of the segment */ @@ -1685,8 +1685,7 @@
NTSTATUS NTAPI -MiReadFilePage -(PFILE_OBJECT FileObject, PLARGE_INTEGER Offset, PPFN_TYPE Page, BOOLEAN Locked); +MiReadFilePage(PFILE_OBJECT FileObject, PLARGE_INTEGER Offset, PPFN_TYPE Page);
VOID NTAPI @@ -1744,15 +1743,11 @@
VOID NTAPI -_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line); - -VOID -NTAPI -_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line); - -#define MmLockSectionSegment(S) _MmLockSectionSegment(S,__FILE__,__LINE__) - -#define MmUnlockSectionSegment(S) _MmUnlockSectionSegment(S,__FILE__,__LINE__) +MmLockSectionSegment(PMM_SECTION_SEGMENT Segment); + +VOID +NTAPI +MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment);
VOID MmspCompleteAndReleasePageOp(PMM_PAGEOP PageOp);
Modified: branches/arty-newcc/ntoskrnl/io/iomgr/device.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/io/iomgr/dev... ============================================================================== --- branches/arty-newcc/ntoskrnl/io/iomgr/device.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/io/iomgr/device.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -1150,11 +1150,7 @@ NTSTATUS Status;
/* Make sure there's a VPB */ - if (!FileSystemDeviceObject->Vpb) - { - DPRINT1("STATUS_INVALID_PARAMETER\n"); - return STATUS_INVALID_PARAMETER; - } + if (!FileSystemDeviceObject->Vpb) return STATUS_INVALID_PARAMETER;
/* Acquire it */ IoAcquireVpbSpinLock(&OldIrql); @@ -1186,7 +1182,6 @@ else { /* Fail */ - DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; }
Modified: branches/arty-newcc/ntoskrnl/io/iomgr/iofunc.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/io/iomgr/iof... ============================================================================== --- branches/arty-newcc/ntoskrnl/io/iomgr/iofunc.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/io/iomgr/iofunc.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -278,7 +278,6 @@ { /* Fail */ ObDereferenceObject(FileObject); - DPRINT1("STATUS_INVALID_PARAMETER\n"); return STATUS_INVALID_PARAMETER; }
@@ -1123,7 +1122,6 @@ /* Check if CompletionFilter is valid */ if (!CompletionFilter || (CompletionFilter & ~FILE_NOTIFY_VALID_MASK)) { - DPRINT1("STATUS_INVALID_PARAMETER\n"); return STATUS_INVALID_PARAMETER; } } @@ -2052,7 +2050,6 @@ /* Otherwise, this was async I/O without a byte offset, so fail */ if (EventObject) ObDereferenceObject(EventObject); ObDereferenceObject(FileObject); - DPRINT1("STATUS_INVALID_PARAMETER\n"); return STATUS_INVALID_PARAMETER; }
@@ -2427,7 +2424,6 @@ (FileObject->CompletionContext)) { /* Fail */ - DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; } else @@ -2462,7 +2458,6 @@ */ ExFreePool(Context); ObDereferenceObject(Queue); - DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; } } @@ -2908,7 +2903,6 @@ /* Otherwise, this was async I/O without a byte offset, so fail */ if (EventObject) ObDereferenceObject(EventObject); ObDereferenceObject(FileObject); - DPRINT1("STATUS_INVALID_PARAMETER\n"); return STATUS_INVALID_PARAMETER; }
Modified: branches/arty-newcc/ntoskrnl/io/iomgr/rawfs.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/io/iomgr/raw... ============================================================================== --- branches/arty-newcc/ntoskrnl/io/iomgr/rawfs.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/io/iomgr/rawfs.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -239,7 +239,6 @@ else { /* Invalid create request */ - DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; } @@ -436,7 +435,6 @@ default:
/* Fail */ - DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } @@ -578,7 +576,6 @@ DeviceObject->AlignmentRequirement)) { /* It's not, fail */ - DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; } else @@ -851,7 +848,6 @@ default:
/* Fail it */ - DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; }
Modified: branches/arty-newcc/ntoskrnl/mm/anonmem.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/anonmem.c... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/anonmem.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/anonmem.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -377,10 +377,13 @@ /* * Try to allocate a page */ - MmUnlockAddressSpace(AddressSpace); - Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); - MmLockAddressSpace(AddressSpace); - + Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page); + if (Status == STATUS_NO_MEMORY) + { + MmUnlockAddressSpace(AddressSpace); + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); + MmLockAddressSpace(AddressSpace); + } if (!NT_SUCCESS(Status)) { DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status);
Modified: branches/arty-newcc/ntoskrnl/mm/balance.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/balance.c... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/balance.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/balance.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -32,17 +32,18 @@ /* GLOBALS ******************************************************************/
MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM]; -static ULONG MiMinimumAvailablePages = 512; +static ULONG MiMinimumAvailablePages; static ULONG MiNrTotalPages; static LIST_ENTRY AllocationListHead; static KSPIN_LOCK AllocationListLock; -static ULONG MiMinimumPagesPerRun = 128; +static ULONG MiPagesRequired = 0; +static ULONG MiMinimumPagesPerRun = 10;
static CLIENT_ID MiBalancerThreadId; static HANDLE MiBalancerThreadHandle = NULL; static KEVENT MiBalancerEvent; -static KEVENT MiBalancerContinue; static KTIMER MiBalancerTimer; +static LONG MiBalancerWork = 0;
/* FUNCTIONS ****************************************************************/
@@ -66,6 +67,7 @@ MiNrTotalPages = NrAvailablePages;
/* Set up targets. */ + MiMinimumAvailablePages = 64; if ((NrAvailablePages + NrSystemPages) >= 8192) { MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3; @@ -115,7 +117,7 @@ if (MmGetReferenceCountPage(Page) == 1) { (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed); - if (IsListEmpty(&AllocationListHead)) + if (IsListEmpty(&AllocationListHead) || MmAvailablePages < MiMinimumAvailablePages) { KeReleaseSpinLock(&AllocationListLock, OldIrql); OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); @@ -127,8 +129,7 @@ Entry = RemoveHeadList(&AllocationListHead); Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry); KeReleaseSpinLock(&AllocationListLock, OldIrql); - if(Consumer == MC_USER || Consumer == MC_PPOOL) - MmRemoveLRUUserPage(Page); + if(Consumer == MC_USER) MmRemoveLRUUserPage(Page); MiZeroPage(Page); Request->Page = Page; KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE); @@ -137,10 +138,33 @@ else { KeReleaseSpinLock(&AllocationListLock, OldIrql); + if(Consumer == MC_USER) MmRemoveLRUUserPage(Page); + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); MmDereferencePage(Page); + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); }
return(STATUS_SUCCESS); +} + +VOID +NTAPI +MiTrimMemoryConsumer(ULONG Consumer) +{ + LONG Target; + ULONG NrFreedPages; + + Target = MiMemoryConsumers[Consumer].PagesUsed - + MiMemoryConsumers[Consumer].PagesTarget; + if (Target < 1) + { + Target = 1; + } + + if (MiMemoryConsumers[Consumer].Trim != NULL) + { + MiMemoryConsumers[Consumer].Trim(Target, 0, &NrFreedPages); + } }
NTSTATUS @@ -151,35 +175,27 @@ NTSTATUS Status;
(*NrFreedPages) = 0; - DPRINT("Trimming user memory (want %d)\n", Target);
CurrentPage = MmGetLRUFirstUserPage(); while (CurrentPage != 0 && Target > 0) { NextPage = MmGetLRUNextUserPage(CurrentPage); - - DPRINT("Page Out %x\n", CurrentPage); + Status = MmPageOutPhysicalAddress(CurrentPage); - DPRINT("Done %x\n", Status); if (NT_SUCCESS(Status)) { + DPRINT("Succeeded\n"); Target--; (*NrFreedPages)++; } else if (Status == STATUS_PAGEFILE_QUOTA) { - MmRemoveLRUUserPage(CurrentPage); - MmInsertLRULastUserPage(CurrentPage); - return STATUS_SUCCESS; + MmRemoveLRUUserPage(CurrentPage); + MmInsertLRULastUserPage(CurrentPage); }
CurrentPage = NextPage; } - if (CurrentPage) - MmDereferencePage(CurrentPage); - - DPRINT("Done: %d\n", NrFreedPages); - return(STATUS_SUCCESS); }
@@ -192,16 +208,14 @@ ULONG NrFreedPages; NTSTATUS Status;
- Target = (MiMinimumAvailablePages - MmAvailablePages); + Target = (MiMinimumAvailablePages - MmAvailablePages) + MiPagesRequired; Target = max(Target, (LONG) MiMinimumPagesPerRun);
for (i = 0; i < MC_MAXIMUM && Target > 0; i++) { if (MiMemoryConsumers[i].Trim != NULL) { - DPRINT("Trimming %d\n"); - Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages); - DPRINT("Got %d pages\n", NrFreedPages); + Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages); if (!NT_SUCCESS(Status)) { KeBugCheck(MEMORY_MANAGEMENT); @@ -215,7 +229,7 @@ MiIsBalancerThread(VOID) { return MiBalancerThreadHandle != NULL && - PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread; + PsGetCurrentThread() == MiBalancerThreadId.UniqueThread; }
NTSTATUS @@ -223,67 +237,106 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, PPFN_TYPE AllocatedPage) { - PFN_TYPE Page = 0; + ULONG OldUsed; + PFN_TYPE Page; KIRQL OldIrql;
- (void)InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed); - - if (!MiIsBalancerThread() && MmAvailablePages <= MiMinimumAvailablePages && CanWait) - { - DPRINT("MmAvailablePages %d MiMinimumAvailablePages %d\n", - MmAvailablePages, MiMinimumAvailablePages); - KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE); - KeWaitForSingleObject(&MiBalancerContinue, 0, KernelMode, FALSE, NULL); + /* + * Make sure we don't exceed our individual target. + */ + OldUsed = InterlockedIncrementUL(&MiMemoryConsumers[Consumer].PagesUsed); + if (OldUsed >= (MiMemoryConsumers[Consumer].PagesTarget - 1) && + !MiIsBalancerThread()) + { + if (!CanWait) + { + (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed); + return(STATUS_NO_MEMORY); + } + MiTrimMemoryConsumer(Consumer); }
/* * Allocate always memory for the non paged pool and for the pager thread. */ - if ((Consumer == MC_NPPOOL) || - (Consumer == MC_SYSTEM) || - MiIsBalancerThread() || - (MmAvailablePages > MiMinimumAvailablePages)) + if ((Consumer == MC_NPPOOL) || (Consumer == MC_SYSTEM) || MiIsBalancerThread()) { OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); Page = MmAllocPage(Consumer, 0); KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); - if (!Page && MiIsBalancerThread()) - { - DPRINT1("Can't allocate for balancer: %d vs %d\n", - MmAvailablePages, MiMinimumAvailablePages); + if (Page == 0) + { KeBugCheck(NO_PAGES_AVAILABLE); } + *AllocatedPage = Page; + if (MmAvailablePages <= MiMinimumAvailablePages && + MiBalancerThreadHandle != NULL) + { + KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE); + } + return(STATUS_SUCCESS); }
/* * Make sure we don't exceed global targets. */ - while (!Page) - { - if (!MiIsBalancerThread() || CanWait) - { - KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE); - KeWaitForSingleObject(&MiBalancerContinue, 0, KernelMode, FALSE, NULL); - } - - /* - * Actually allocate the page. - */ - OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); - Page = MmAllocPage(Consumer, 0); - KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); - - if (!Page && !CanWait) - { - (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed); - return(STATUS_NO_MEMORY); - } - } - - if(Consumer == MC_USER || Consumer == MC_PPOOL) - MmInsertLRULastUserPage(Page); + if (MmAvailablePages <= MiMinimumAvailablePages) + { + MM_ALLOCATION_REQUEST Request; + + if (!CanWait) + { + (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed); + return(STATUS_NO_MEMORY); + } + + /* Insert an allocation request. */ + Request.Page = 0; + + KeInitializeEvent(&Request.Event, NotificationEvent, FALSE); + (void)InterlockedIncrementUL(&MiPagesRequired); + + KeAcquireSpinLock(&AllocationListLock, &OldIrql); + + if (MiBalancerThreadHandle != NULL) + { + KeSetEvent(&MiBalancerEvent, IO_NO_INCREMENT, FALSE); + } + InsertTailList(&AllocationListHead, &Request.ListEntry); + KeReleaseSpinLock(&AllocationListLock, OldIrql); + + KeWaitForSingleObject(&Request.Event, + 0, + KernelMode, + FALSE, + NULL); + + Page = Request.Page; + if (Page == 0) + { + KeBugCheck(NO_PAGES_AVAILABLE); + } + /* Update the Consumer */ + MiGetPfnEntry(Page)->u3.e1.PageLocation = Consumer; + if(Consumer == MC_USER) MmInsertLRULastUserPage(Page); + *AllocatedPage = Page; + (void)InterlockedDecrementUL(&MiPagesRequired); + return(STATUS_SUCCESS); + } + + /* + * Actually allocate the page. + */ + OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); + Page = MmAllocPage(Consumer, 0); + KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); + if (Page == 0) + { + KeBugCheck(NO_PAGES_AVAILABLE); + } + if(Consumer == MC_USER) MmInsertLRULastUserPage(Page); *AllocatedPage = Page; - + return(STATUS_SUCCESS); }
@@ -292,11 +345,15 @@ { PVOID WaitObjects[2]; NTSTATUS Status; + ULONG i; + ULONG NrFreedPages; + ULONG NrPagesUsed; + ULONG Target; + BOOLEAN ShouldRun; +
WaitObjects[0] = &MiBalancerEvent; WaitObjects[1] = &MiBalancerTimer; - - ASSERT(MiIsBalancerThread());
while (1) { @@ -309,8 +366,61 @@ NULL, NULL);
- MmRebalanceMemoryConsumers(); - KeSetEvent(&MiBalancerContinue, IO_NO_INCREMENT, FALSE); + if (Status == STATUS_SUCCESS) + { + /* MiBalancerEvent */ + while (MmAvailablePages < MiMinimumAvailablePages + 5) + { + for (i = 0; i < MC_MAXIMUM; i++) + { + if (MiMemoryConsumers[i].Trim != NULL) + { + NrFreedPages = 0; + Status = MiMemoryConsumers[i].Trim(MiMinimumPagesPerRun, 0, &NrFreedPages); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(MEMORY_MANAGEMENT); + } + } + } + } + InterlockedExchange(&MiBalancerWork, 0); + } + else if (Status == STATUS_SUCCESS + 1) + { + /* MiBalancerTimer */ + ShouldRun = MmAvailablePages < MiMinimumAvailablePages + 5 ? TRUE : FALSE; + for (i = 0; i < MC_MAXIMUM; i++) + { + if (MiMemoryConsumers[i].Trim != NULL) + { + NrPagesUsed = MiMemoryConsumers[i].PagesUsed; + if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget || ShouldRun) + { + if (NrPagesUsed > MiMemoryConsumers[i].PagesTarget) + { + Target = max (NrPagesUsed - MiMemoryConsumers[i].PagesTarget, + MiMinimumPagesPerRun); + } + else + { + Target = MiMinimumPagesPerRun; + } + NrFreedPages = 0; + Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages); + if (!NT_SUCCESS(Status)) + { + KeBugCheck(MEMORY_MANAGEMENT); + } + } + } + } + } + else + { + DPRINT1("KeWaitForMultipleObjects failed, status = %x\n", Status); + KeBugCheck(MEMORY_MANAGEMENT); + } } }
@@ -330,7 +440,6 @@
KeInitializeEvent(&MiBalancerEvent, SynchronizationEvent, FALSE); - KeInitializeEvent(&MiBalancerContinue, SynchronizationEvent, FALSE); KeInitializeTimerEx(&MiBalancerTimer, SynchronizationTimer); KeSetTimerEx(&MiBalancerTimer, #if defined(__GNUC__)
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 Nov 27 02:03:24 2009 @@ -99,7 +99,6 @@ return 0; } PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry); - MmReferencePage(PageDescriptor - MmPfnDatabase); ASSERT_PFN(PageDescriptor); KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql); return PageDescriptor - MmPfnDatabase; @@ -116,7 +115,7 @@ Page = MiGetPfnEntry(Pfn); ASSERT(Page); ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED); - ASSERT(Page->Flags.Consumer == MC_USER || Page->Flags.Consumer == MC_PPOOL); + ASSERT(Page->Flags.Consumer == MC_USER); InsertTailList(&UserPageListHead, &Page->ListEntry); KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql); } @@ -134,17 +133,14 @@ Page = MiGetPfnEntry(PreviousPfn); ASSERT(Page); ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED); - ASSERT(Page->Flags.Consumer == MC_USER || Page->Flags.Consumer == MC_PPOOL); + ASSERT(Page->Flags.Consumer == MC_USER); NextListEntry = (PLIST_ENTRY)Page->ListEntry.Flink; if (NextListEntry == &UserPageListHead) { - MmDereferencePage(PreviousPfn); KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql); return 0; } PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry); - MmReferencePage(PageDescriptor - MmPfnDatabase); - MmDereferencePage(PreviousPfn); KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql); return PageDescriptor - MmPfnDatabase; } @@ -910,7 +906,6 @@ NTAPI MmDereferencePage(PFN_TYPE Pfn) { - KIRQL oldIrql; PPHYSICAL_PAGE Page;
DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT); @@ -933,12 +928,7 @@ if (Page->ReferenceCount == 0) { MmAvailablePages++; - if (Page->Flags.Consumer == MC_USER) - { - oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); - RemoveEntryList(&Page->ListEntry); - KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql); - } + if (Page->Flags.Consumer == MC_USER) RemoveEntryList(&Page->ListEntry); if (Page->RmapListHead != (LONG)NULL) { DPRINT1("Freeing page with rmap entries.\n");
Modified: branches/arty-newcc/ntoskrnl/mm/mpw.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/mpw.c?rev... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/mpw.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/mpw.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -17,8 +17,8 @@ /* GLOBALS *******************************************************************/
HANDLE MpwThreadHandle; -CLIENT_ID MpwThreadId; -KEVENT MpwThreadEvent, MpwCompleteEvent; +static CLIENT_ID MpwThreadId; +KEVENT MpwThreadEvent; BOOLEAN MpwThreadShouldTerminate;
/* FUNCTIONS *****************************************************************/ @@ -81,11 +81,12 @@ }
PagesWritten = 0; +#if 0 /* * FIXME: MmWriteDirtyPages doesn't work correctly. */ MmWriteDirtyPages(128, &PagesWritten); - KeSetEvent(&MpwCompleteEvent, IO_NO_INCREMENT, TRUE); +#endif } }
@@ -98,7 +99,6 @@
MpwThreadShouldTerminate = FALSE; KeInitializeEvent(&MpwThreadEvent, SynchronizationEvent, FALSE); - KeInitializeEvent(&MpwCompleteEvent, SynchronizationEvent, FALSE);
Status = PsCreateSystemThread(&MpwThreadHandle, THREAD_ALL_ACCESS,
Modified: branches/arty-newcc/ntoskrnl/mm/pageop.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/pageop.c?... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/pageop.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/pageop.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -83,11 +83,11 @@ */ if (MArea->Type == MEMORY_AREA_SECTION_VIEW) { - Hash = (((ULONG_PTR)Segment) ^ (((ULONG_PTR)Offset) / PAGE_SIZE)); + Hash = (((ULONG_PTR)Segment) | (((ULONG_PTR)Offset) / PAGE_SIZE)); } else { - Hash = (((ULONG_PTR)Pid) ^ (((ULONG_PTR)Address) / PAGE_SIZE)); + Hash = (((ULONG_PTR)Pid) | (((ULONG_PTR)Address) / PAGE_SIZE)); } Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
@@ -151,11 +151,11 @@ */ if (MArea->Type == MEMORY_AREA_SECTION_VIEW) { - Hash = (((ULONG_PTR)Segment) ^ (((ULONG_PTR)Offset) / PAGE_SIZE)); + Hash = (((ULONG_PTR)Segment) | (((ULONG_PTR)Offset) / PAGE_SIZE)); } else { - Hash = (((ULONG_PTR)Pid) ^ (((ULONG_PTR)Address) / PAGE_SIZE)); + Hash = (((ULONG_PTR)Pid) | (((ULONG_PTR)Address) / PAGE_SIZE)); } Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
Modified: branches/arty-newcc/ntoskrnl/mm/rmap.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/rmap.c?re... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/rmap.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/rmap.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -32,7 +32,6 @@
/* GLOBALS ******************************************************************/
-ULONG RmapPagingOut = 0; static FAST_MUTEX RmapListLock; static NPAGED_LOOKASIDE_LIST RmapLookasideList;
@@ -63,7 +62,7 @@ ULONG Type; PVOID Address; PEPROCESS Process; - PMM_PAGEOP PageOp = NULL; + PMM_PAGEOP PageOp; ULONG Offset; NTSTATUS Status = STATUS_SUCCESS;
@@ -122,7 +121,6 @@ { Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
-#ifndef _NEWCC_ /* * Get or create a pageop */ @@ -139,7 +137,6 @@ } return(STATUS_UNSUCCESSFUL); } -#endif
/* * Release locks now we have a page op. @@ -208,7 +205,7 @@ ULONG Type; PVOID Address; PEPROCESS Process; - PMM_PAGEOP PageOp = NULL; + PMM_PAGEOP PageOp; ULONG Offset; NTSTATUS Status = STATUS_SUCCESS;
@@ -258,7 +255,6 @@ { Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
-#ifndef _NEWCC_ /* * Get or create a pageop */ @@ -274,7 +270,6 @@ } return(STATUS_UNSUCCESSFUL); } -#endif
/* * Release locks now we have a page op. @@ -393,8 +388,6 @@ { PMM_RMAP_ENTRY current_entry;
- ASSERT(Page); - ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); if (current_entry == NULL) @@ -416,8 +409,6 @@ { PMM_RMAP_ENTRY current_entry;
- ASSERT(Page); - ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); if (current_entry == NULL) @@ -438,8 +429,6 @@ MmIsDirtyPageRmap(PFN_TYPE Page) { PMM_RMAP_ENTRY current_entry; - - ASSERT(Page);
ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); @@ -470,7 +459,6 @@ PMM_RMAP_ENTRY new_entry; ULONG PrevSize;
- ASSERT(Page); Address = (PVOID)PAGE_ROUND_DOWN(Address);
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList); @@ -542,8 +530,6 @@ PMM_RMAP_ENTRY previous_entry; PEPROCESS Process;
- ASSERT(Page); - ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); if (current_entry == NULL) @@ -581,8 +567,6 @@ PVOID Address) { PMM_RMAP_ENTRY current_entry, previous_entry; - - ASSERT(Page);
ExAcquireFastMutex(&RmapListLock); previous_entry = NULL;
Modified: branches/arty-newcc/ntoskrnl/mm/section/data.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/section/d... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/section/data.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/section/data.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -122,18 +122,18 @@
VOID NTAPI -_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line) -{ - DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line); - KeAcquireGuardedMutex(&Segment->Lock); +MmLockSectionSegment(PMM_SECTION_SEGMENT Segment) +{ + DPRINT("MmLockSectionSegment(%p)\n", Segment); + ExAcquireFastMutex(&Segment->Lock); }
VOID NTAPI -_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line) -{ - DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line); - KeReleaseGuardedMutex(&Segment->Lock); +MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment) +{ + ExReleaseFastMutex(&Segment->Lock); + DPRINT("MmUnlockSectionSegment(%p)\n", Segment); }
VOID @@ -233,7 +233,7 @@
NTSTATUS NTAPI -MiReadFilePage(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PPFN_TYPE Page, BOOLEAN Locked) +MiReadFilePage(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PPFN_TYPE Page) { PFN_TYPE XPage; NTSTATUS Status; @@ -255,8 +255,7 @@ return Status; } - if (!Locked) - MmLockAddressSpace(MmGetKernelAddressSpace()); + MmLockAddressSpace(MmGetKernelAddressSpace()); Status = MmCreateMemoryArea (MmGetKernelAddressSpace(), MEMORY_AREA_VIRTUAL_MEMORY, @@ -272,8 +271,7 @@ if (!NT_SUCCESS(Status)) { DPRINT1("STATUS_NO_MEMORY: %x\n", Status); - if (!Locked) - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); MmReleasePageMemoryConsumer(MC_USER, *Page); return STATUS_NO_MEMORY; } @@ -282,15 +280,13 @@ if (!NT_SUCCESS(Status)) { MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); - if (!Locked) - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + MmUnlockAddressSpace(MmGetKernelAddressSpace()); MmReleasePageMemoryConsumer(MC_USER, *Page); DPRINT1("Status: %x\n", Status); return Status; } - if (!Locked) - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + MmUnlockAddressSpace(MmGetKernelAddressSpace());
MiZeroPage(*Page); Status = MiSimpleRead @@ -302,13 +298,11 @@ DPRINT("Read Status %x (Page %x)\n", Status, *Page);
- if (!Locked) - MmLockAddressSpace(MmGetKernelAddressSpace()); + MmLockAddressSpace(MmGetKernelAddressSpace()); MmDeleteVirtualMapping(NULL, PageBuf, FALSE, NULL, &XPage); ASSERT(XPage == *Page); MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); - if (!Locked) - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + MmUnlockAddressSpace(MmGetKernelAddressSpace());
if (!NT_SUCCESS(Status)) { @@ -383,11 +377,9 @@ DPRINT("Reading at offset %08x%08x (relative %x)\n", TotalOffset.HighPart, TotalOffset.LowPart, Offset); MmUnlockSectionSegment(Segment); - if (!Locked) - MmUnlockAddressSpace(AddressSpace); - Status = MiReadFilePage(Segment->FileObject, &TotalOffset, &Page, Locked); - if (!Locked) - MmLockAddressSpace(AddressSpace); + MmUnlockAddressSpace(AddressSpace); + Status = MiReadFilePage(Segment->FileObject, &TotalOffset, &Page); + MmLockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status)) { @@ -430,23 +422,10 @@ SWAPENTRY SwapEntry;
MmDeletePageFileMapping(Process, (PVOID)PAddress, &SwapEntry); - MmUnlockSectionSegment(Segment); - if (!Locked) - MmUnlockAddressSpace(AddressSpace); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { ASSERT(FALSE); - } - - MmLockSectionSegment(Segment); - - if (!Locked) - MmLockAddressSpace(AddressSpace); - if (!MmIsPageSwapEntry(Process, PAddress)) - { - // Handled elsewhere - return STATUS_SUCCESS; }
Status = MmReadFromSwapPage(SwapEntry, Page); @@ -455,7 +434,6 @@ DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status); ASSERT(FALSE); } - DPRINT("CreateVirtualMapping: %x -> %x\n", Address, Attributes); Status = MmCreateVirtualMapping(Process, Address, @@ -590,20 +568,17 @@ MiCopyFromUserPage(PFN_TYPE DestPage, PVOID SourceAddress) { PEPROCESS Process; - KIRQL PrimaryIrql, Irql; + KIRQL Irql; PVOID TempAddress;
Process = PsGetCurrentProcess(); - PrimaryIrql = KfRaiseIrql(DISPATCH_LEVEL); TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql); if (TempAddress == NULL) { - KfLowerIrql(PrimaryIrql); return(STATUS_NO_MEMORY); } memcpy(TempAddress, SourceAddress, PAGE_SIZE); MiUnmapPageInHyperSpace(Process, TempAddress, Irql); - KfLowerIrql(PrimaryIrql); return(STATUS_SUCCESS); }
@@ -682,9 +657,7 @@ /* * Allocate a page */ - MmUnlockSectionSegment(Segment); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage); - if (!NT_SUCCESS(Status)) { ASSERT(FALSE); @@ -695,15 +668,6 @@ * Copy the old page */ MiCopyFromUserPage(NewPage, PAddress); - - MmLockSectionSegment(Segment); - if (MmGetPfnForProcess(Process, PAddress) != OldPage) - { - // Handled elsewhere - MmReleasePageMemoryConsumer(MC_USER, NewPage); - MmUnlockSectionSegment(Segment); - return STATUS_SUCCESS; - }
/* * Delete the old entry. @@ -870,39 +834,26 @@ ("Pulling zero pages for %08x%08x-%08x%08x\n", FileOffset.u.HighPart, FileOffset.u.LowPart, End.u.HighPart, End.u.LowPart); - MmLockSectionSegment(Segment); while (FileOffset.QuadPart < End.QuadPart) { PVOID Address; ULONG Entry = MiGetPageEntrySectionSegment(Segment, &FileOffset); - if (Entry == 0) { - MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); - if (!NT_SUCCESS(MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page))) { + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); return STATUS_NO_MEMORY; } - - MmLockAddressSpace(AddressSpace); - MmLockSectionSegment(Segment); Address = ((PCHAR)MemoryArea->StartingAddress) + FileOffset.QuadPart - FirstMapped.QuadPart; - - if (!MmIsPagePresent(NULL, Address) && MiGetPageEntrySectionSegment(Segment, &FileOffset) == Entry) - { - MmCreateVirtualMapping(NULL, Address, PAGE_READWRITE, &Page, 1); - MmInsertRmap(Page, NULL, Address); - MiSetPageEntrySectionSegment(Segment, &FileOffset, MAKE_SSE(Page << PAGE_SHIFT, 1)); - } - else - MmReleasePageMemoryConsumer(MC_USER, Page); + MmCreateVirtualMapping(NULL, Address, PAGE_READWRITE, &Page, 1); + MmInsertRmap(Page, NULL, Address); + MiSetPageEntrySectionSegment(Segment, &FileOffset, MAKE_SSE(Page << PAGE_SHIFT, 1)); } FileOffset.QuadPart += PAGE_SIZE; } - MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); return STATUS_SUCCESS; @@ -1049,6 +1000,8 @@ }
MmReleasePageMemoryConsumer(MC_USER, Page); + PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); } else if (!Context.WasDirty && Context.Private && SwapEntry != 0) @@ -1064,6 +1017,8 @@ ASSERT(FALSE); } MmReleasePageMemoryConsumer(MC_USER, Page); + PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); }
@@ -1112,6 +1067,8 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); } MmUnlockAddressSpace(AddressSpace); + PageOp->Status = STATUS_UNSUCCESSFUL; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_PAGEFILE_QUOTA); } } @@ -1156,6 +1113,8 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); } MmUnlockAddressSpace(AddressSpace); + PageOp->Status = STATUS_UNSUCCESSFUL; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_UNSUCCESSFUL); }
@@ -1184,6 +1143,8 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); }
+ PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); }
@@ -1198,8 +1159,10 @@ PROS_SECTION_OBJECT Section; PMM_SECTION_SEGMENT Segment; PFN_TYPE Page; + SWAPENTRY SwapEntry; ULONG Entry; - NTSTATUS Status = STATUS_SUCCESS; + BOOLEAN Private; + NTSTATUS Status; PFILE_OBJECT FileObject; PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
@@ -1220,38 +1183,83 @@ /* * Get the section segment entry and the physical address. */ - MmLockAddressSpace(AddressSpace); - MmLockSectionSegment(Segment); - Entry = MiGetPageEntrySectionSegment(Segment, &Offset); + if (!MmIsPagePresent(Process, Address)) + { + DPRINT1("Trying to page out not-present page at (%d,0x%.8X).\n", + Process ? Process->UniqueProcessId : 0, Address); + ASSERT(FALSE); + } Page = MmGetPfnForProcess(Process, Address); - - if (!Page) - { - // Somebody else already paged it out - MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); - return STATUS_SUCCESS; - } + SwapEntry = MmGetSavedSwapEntryPage(Page);
/* * Check for a private (COWed) page. */ - if (!IS_SWAP_FROM_SSE(Entry) && PFN_FROM_SSE(Entry) == Page && MmIsDirtyPageRmap(Page)) - { - MmSetCleanAllRmaps(Page); - DPRINT("MiWriteBackPage(%wZ,%08x%08x)\n", &FileObject->FileName, Offset.u.HighPart, Offset.u.LowPart); - MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); - Status = MiWriteBackPage(FileObject, &Offset, PAGE_SIZE, Page); + if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page) + { + Private = TRUE; } else { - MmUnlockAddressSpace(AddressSpace); - MmUnlockSectionSegment(Segment); - } - - return(Status); + Private = FALSE; + } + + /* + * Speculatively set all mappings of the page to clean. + */ + MmSetCleanAllRmaps(Page); + + /* + * If this page was direct mapped from the cache then the cache manager + * will take care of writing it back to disk. + */ + if (!Private) + { + ASSERT(SwapEntry == 0); + DPRINT("MiWriteBackPage(%wZ,%08x%08x)\n", &FileObject->FileName, Offset.u.HighPart, Offset.u.LowPart); + Status = PageOp->Status = MiWriteBackPage(FileObject, &Offset, PAGE_SIZE, Page); + MmspCompleteAndReleasePageOp(PageOp); + return(Status); + } + + /* + * If necessary, allocate an entry in the paging file for this page + */ + if (SwapEntry == 0) + { + SwapEntry = MmAllocSwapPage(); + if (SwapEntry == 0) + { + MmSetDirtyAllRmaps(Page); + PageOp->Status = STATUS_UNSUCCESSFUL; + MmspCompleteAndReleasePageOp(PageOp); + return(STATUS_PAGEFILE_QUOTA); + } + MmSetSavedSwapEntryPage(Page, SwapEntry); + } + + /* + * Write the page to the pagefile + */ + Status = MmWriteToSwapPage(SwapEntry, Page); + if (!NT_SUCCESS(Status)) + { + DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", + Status); + MmSetDirtyAllRmaps(Page); + PageOp->Status = STATUS_UNSUCCESSFUL; + MmspCompleteAndReleasePageOp(PageOp); + return(STATUS_UNSUCCESSFUL); + } + + /* + * Otherwise we have succeeded. + */ + DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT); + PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); + return(STATUS_SUCCESS); }
NTSTATUS @@ -1283,6 +1291,8 @@ Segment = MemoryArea->Data.SectionData.Segment; ViewOffset.QuadPart = MemoryArea->Data.SectionData.ViewOffset.QuadPart;
+ MmLockSectionSegment(Segment); + Pages = ExAllocatePool (NonPagedPool, sizeof(PFN_TYPE) * @@ -1292,8 +1302,6 @@ { ASSERT(FALSE); } - - MmLockSectionSegment(Segment);
for (PageAddress = BeginningAddress; PageAddress < EndingAddress; @@ -1328,10 +1336,8 @@ { DPRINT("MiWriteBackPage(%wZ,%08x%08x)\n", &Segment->FileObject->FileName, FileOffset.u.HighPart, FileOffset.u.LowPart); Status = MiWriteBackPage(Segment->FileObject, &FileOffset, PAGE_SIZE, Page); - MmLockAddressSpace(AddressSpace); MmUnlockPage(Page); MmSetCleanAllRmaps(Page); - MmUnlockAddressSpace(AddressSpace); if (!NT_SUCCESS(Status)) { DPRINT1 @@ -1689,7 +1695,7 @@ return(STATUS_NO_MEMORY); }
- KeInitializeGuardedMutex(&Segment->Lock); + ExInitializeFastMutex(&Segment->Lock);
Segment->ReferenceCount = 1; Section->Segment = Segment; @@ -1707,7 +1713,7 @@ /* * Set the lock before assigning the segment to the file object */ - KeAcquireGuardedMutex(&Segment->Lock); + ExAcquireFastMutex(&Segment->Lock);
DPRINT("Filling out Segment info (No previous data section)\n"); ObReferenceObject(FileObject); @@ -2327,6 +2333,50 @@ return(STATUS_SUCCESS); }
+NTSTATUS +NTAPI +MiAwaitPageOps(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PVOID BaseAddress) +{ + NTSTATUS Status; + PMM_PAGEOP PageOp; + ULONG Offset; + + while (MemoryArea->PageOpCount) + { + Offset = PAGE_ROUND_UP((ULONG_PTR)MemoryArea->EndingAddress - (ULONG_PTR)MemoryArea->StartingAddress); + + while (Offset) + { + Offset -= PAGE_SIZE; + PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, + MemoryArea->Data.SectionData.Segment, + Offset); + if (PageOp) + { + MmUnlockAddressSpace(AddressSpace); + Status = MmspWaitForPageOpCompletionEvent(PageOp); + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op, status = %x\n", Status); + ASSERT(FALSE); + } + MmLockAddressSpace(AddressSpace); + MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, + BaseAddress); + if (MemoryArea == NULL || + MemoryArea->Type != MEMORY_AREA_SECTION_VIEW) + { + MmUnlockAddressSpace(AddressSpace); + DPRINT("STATUS_NOT_MAPPED_VIEW\n"); + return STATUS_NOT_MAPPED_VIEW; + } + break; + } + } + } + return STATUS_SUCCESS; +} + /* * @implemented */ @@ -2359,14 +2409,18 @@ if (MemoryArea->Type == MEMORY_AREA_IMAGE_SECTION) { MemoryArea->DeleteInProgress = TRUE; - Status = MiUnmapImageSection(AddressSpace, MemoryArea, BaseAddress); + Status = MiAwaitPageOps(AddressSpace, MemoryArea, BaseAddress); + if (NT_SUCCESS(Status)) + Status = MiUnmapImageSection(AddressSpace, MemoryArea, BaseAddress); } else if (MemoryArea->Type == MEMORY_AREA_PHYSICAL_MEMORY_SECTION || MemoryArea->Type == MEMORY_AREA_PAGE_FILE_SECTION || MemoryArea->Type == MEMORY_AREA_SECTION_VIEW) { MemoryArea->DeleteInProgress = TRUE; - Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress); + Status = MiAwaitPageOps(AddressSpace, MemoryArea, BaseAddress); + if (NT_SUCCESS(Status)) + Status = MmUnmapViewOfSegment(AddressSpace, BaseAddress); } else {
Modified: branches/arty-newcc/ntoskrnl/mm/section/image.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/section/i... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/section/image.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/section/image.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -233,17 +233,14 @@ Entry = MiGetPageEntrySectionSegment(Segment, &Offset); HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
- if (Entry == 0 && !HasSwapEntry && - (Offset.QuadPart < PAGE_ROUND_UP(Segment->RawLength.QuadPart))) + if (Entry == 0 && !HasSwapEntry && Offset.QuadPart < PAGE_ROUND_UP(Segment->RawLength.QuadPart)) { TotalOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset/*.QuadPart*/;
MmUnlockSectionSegment(Segment); - if (!Locked) - MmUnlockAddressSpace(AddressSpace); - Status = MiReadFilePage(Section->FileObject, &TotalOffset, &Page, Locked); - if (!Locked) - MmLockAddressSpace(AddressSpace); + MmUnlockAddressSpace(AddressSpace); + Status = MiReadFilePage(Section->FileObject, &TotalOffset, &Page); + MmLockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status)) { @@ -285,15 +282,10 @@
MmDeletePageFileMapping(Process, (PVOID)PAddress, &SwapEntry);
- MmUnlockSectionSegment(Segment); - if (!Locked) - MmUnlockAddressSpace(AddressSpace); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { - if (!Locked) - MmLockAddressSpace(AddressSpace); - return Status; + ASSERT(FALSE); } DPRINT("Allocated page %x\n", Page);
@@ -304,14 +296,6 @@ ASSERT(FALSE); } MmLockAddressSpace(AddressSpace); - MmLockSectionSegment(Segment); - if (MmIsPagePresent(Process, Address)) - { - // Handled elsewhere - MmReleasePageMemoryConsumer(MC_USER, Page); - MmUnlockSectionSegment(Segment); - return STATUS_SUCCESS; - } Status = MmCreateVirtualMapping(Process, Address, Region->Protect, @@ -351,26 +335,16 @@ */ if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { - MmUnlockSectionSegment(Segment); - if (!Locked) - MmUnlockAddressSpace(AddressSpace); + MmUnlockAddressSpace(AddressSpace); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { DPRINT("Status %x\n", Status); - if (!Locked) - MmLockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); return Status; } DPRINT("Allocated page %x\n", Page); - if (!Locked) - MmLockAddressSpace(AddressSpace); - if (MmIsPagePresent(Process, Address)) - { - // Handled elsewhere - MmReleasePageMemoryConsumer(MC_USER, Page); - return STATUS_SUCCESS; - } + MmLockAddressSpace(AddressSpace); Status = MmCreateVirtualMapping(Process, Address, Region->Protect, @@ -380,6 +354,7 @@ { MmReleasePageMemoryConsumer(MC_USER, Page); DPRINT("Release page %x\n", Page); + MmUnlockSectionSegment(Segment); return(Status); } MmInsertRmap(Page, Process, (PVOID)PAddress); @@ -391,6 +366,7 @@ /* * Cleanup and release locks */ + MmUnlockSectionSegment(Segment); //DPRINT("Address 0x%.8X\n", Address); return(STATUS_SUCCESS); } @@ -410,9 +386,7 @@ /* * Release all our locks and read in the page from disk */ - MmUnlockSectionSegment(Segment); - if (!Locked) - MmUnlockAddressSpace(AddressSpace); + MmUnlockAddressSpace(AddressSpace);
if (Offset.QuadPart >= PAGE_ROUND_UP(Segment->RawLength.QuadPart)) { @@ -420,8 +394,8 @@ if (!NT_SUCCESS(Status)) { DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status); - if (!Locked) - MmLockAddressSpace(AddressSpace); + MmLockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); return Status; } DPRINT("Allocated page %x\n", Page); @@ -435,8 +409,8 @@ DPRINT1("Unable to create virtual mapping\n"); MmReleasePageMemoryConsumer(MC_USER, Page); DPRINT("Release page %x\n", Page); - if (!Locked) - MmLockAddressSpace(AddressSpace); + MmLockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); return Status; } } @@ -452,8 +426,8 @@ DPRINT1("Unable to create virtual mapping\n"); MmReleasePageMemoryConsumer(MC_USER, Page); DPRINT("Release page %x\n", Page); - if (!Locked) - MmLockAddressSpace(AddressSpace); + MmLockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); return Status; }
@@ -463,21 +437,12 @@ /* * Relock the address space and segment */ - if (!Locked) - MmLockAddressSpace(AddressSpace); + MmLockAddressSpace(AddressSpace);
/* * Mark the offset within the section as having valid, in-memory * data */ - MmLockSectionSegment(Segment); - if (Entry != MiGetPageEntrySectionSegment(Segment, &Offset)) - { - // Handled elsewhere - MmUnlockSectionSegment(Segment); - return STATUS_SUCCESS; - } - Entry = MAKE_SSE(Page << PAGE_SHIFT, 1); MiSetPageEntrySectionSegment(Segment, &Offset, Entry);
@@ -532,8 +497,6 @@ //DPRINT("Address 0x%.8X\n", Address); return(STATUS_SUCCESS); } - - ASSERT(FALSE); }
NTSTATUS @@ -1437,7 +1400,7 @@ /* And finish their initialization */ for ( i = 0; i < ImageSectionObject->NrSegments; ++ i ) { - KeInitializeGuardedMutex(&ImageSectionObject->Segments[i].Lock); + ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock); ImageSectionObject->Segments[i].Flags = MM_IMAGE_SEGMENT; ImageSectionObject->Segments[i].ReferenceCount = 1; MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]); @@ -1885,6 +1848,8 @@ //DPRINT("MiUnmapImageSection @ %x\n", BaseAddress); MemoryArea->DeleteInProgress = TRUE;
+ MiAwaitPageOps(AddressSpace, MemoryArea, BaseAddress); + Section = MemoryArea->Data.SectionData.Section;
if (Section->AllocationAttributes & SEC_IMAGE)
Modified: branches/arty-newcc/ntoskrnl/mm/section/io.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/section/i... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/section/io.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/section/io.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -54,6 +54,8 @@ #pragma alloc_text(INIT, MmInitSectionImplementation) #endif
+KEVENT CcpLazyWriteEvent; + /* * FUNCTION: Waits in kernel mode indefinitely for a file object lock. * ARGUMENTS: PFILE_OBJECT to wait for. @@ -426,65 +428,82 @@ ULONG Length, PFN_TYPE Page) { - PFN_TYPE XPage; NTSTATUS Status; + PVOID Hyperspace; IO_STATUS_BLOCK Iosb; - PVOID PageBuf = 0; - PMEMORY_AREA TmpArea; - PHYSICAL_ADDRESS BoundaryAddressMultiple; - - BoundaryAddressMultiple.QuadPart = 0; - - MmLockAddressSpace(MmGetKernelAddressSpace()); - - Status = MmCreateMemoryArea - (MmGetKernelAddressSpace(), - MEMORY_AREA_VIRTUAL_MEMORY, - &PageBuf, - PAGE_SIZE, - PAGE_READWRITE, - &TmpArea, - FALSE, - MEM_TOP_DOWN, - BoundaryAddressMultiple); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("STATUS_NO_MEMORY: %x\n", Status); - MmUnlockAddressSpace(MmGetKernelAddressSpace()); - return STATUS_NO_MEMORY; - } - - Status = MmCreateVirtualMapping(NULL, PageBuf, PAGE_READWRITE, &Page, 1); - if (!NT_SUCCESS(Status)) - { - MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); - MmUnlockAddressSpace(MmGetKernelAddressSpace()); - DPRINT1("Status: %x\n", Status); - return Status; - } - MmReferencePage(Page); - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + KIRQL OldIrql; + PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE); + + if (!PageBuffer) return STATUS_NO_MEMORY; + + OldIrql = KfRaiseIrql(DISPATCH_LEVEL); + Hyperspace = MmCreateHyperspaceMapping(Page); + RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE); + MmDeleteHyperspaceMapping(Hyperspace); + KfLowerIrql(OldIrql);
DPRINT("MiWriteBackPage(%wZ,%08x%08x)\n", &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart); Status = MiSimpleWrite (FileObject, FileOffset, - PageBuf, + PageBuffer, Length, &Iosb);
+ ExFreePool(PageBuffer); + if (!NT_SUCCESS(Status)) { DPRINT1("MiSimpleWrite failed (%x)\n", Status); }
- MmLockAddressSpace(MmGetKernelAddressSpace()); - MmDeleteVirtualMapping(NULL, PageBuf, FALSE, NULL, &XPage); - ASSERT(XPage == Page); - MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); - MmDereferencePage(Page); - MmUnlockAddressSpace(MmGetKernelAddressSpace()); - return Status; } + +VOID +NTAPI +MiWriteThread() +{ + BOOLEAN Complete; + NTSTATUS Status; + LIST_ENTRY OldHead; + PLIST_ENTRY Entry; + PWRITE_SCHEDULE_ENTRY WriteEntry; + + ExAcquireFastMutex(&MiWriteMutex); + Complete = IsListEmpty(&MiWriteScheduleListHead); + ExReleaseFastMutex(&MiWriteMutex); + if (Complete) + { + DPRINT1("No items await writing\n"); + KeSetEvent(&CcpLazyWriteEvent, IO_NO_INCREMENT, FALSE); + } + + DPRINT1("Lazy write items are available\n"); + KeResetEvent(&CcpLazyWriteEvent); + + ExAcquireFastMutex(&MiWriteMutex); + RtlCopyMemory(&OldHead, &MiWriteScheduleListHead, sizeof(OldHead)); + OldHead.Flink->Blink = &OldHead; + OldHead.Blink->Flink = &OldHead; + InitializeListHead(&MiWriteScheduleListHead); + ExReleaseFastMutex(&MiWriteMutex); + + for (Entry = OldHead.Flink; + !IsListEmpty(&OldHead); + Entry = OldHead.Flink) + { + WriteEntry = CONTAINING_RECORD(Entry, WRITE_SCHEDULE_ENTRY, Entry); + Status = MiWriteBackPage(WriteEntry->FileObject, &WriteEntry->FileOffset, WriteEntry->Length, WriteEntry->Page); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("MiSimpleWrite failed (%x)\n", Status); + } + + MmDereferencePage(WriteEntry->Page); + ObDereferenceObject(WriteEntry->FileObject); + RemoveEntryList(&WriteEntry->Entry); + ExFreePool(WriteEntry); + } +}
Modified: branches/arty-newcc/ntoskrnl/mm/section/pagefile.c URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/section/p... ============================================================================== --- branches/arty-newcc/ntoskrnl/mm/section/pagefile.c [iso-8859-1] (original) +++ branches/arty-newcc/ntoskrnl/mm/section/pagefile.c [iso-8859-1] Fri Nov 27 02:03:24 2009 @@ -69,7 +69,9 @@ PROS_SECTION_OBJECT Section; PMM_SECTION_SEGMENT Segment; ULONG Entry; + ULONG Entry1; ULONG Attributes; + PMM_PAGEOP PageOp; PMM_REGION Region; BOOLEAN HasSwapEntry; PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace); @@ -98,14 +100,10 @@ Region = MmFindRegion(MemoryArea->StartingAddress, &MemoryArea->Data.SectionData.RegionListHead, Address, NULL); - /* * Lock the segment */ MmLockSectionSegment(Segment); - - Entry = MiGetPageEntrySectionSegment(Segment, &Offset); - HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress);
/* * Check if this page needs to be mapped COW @@ -121,63 +119,178 @@ Attributes = Region->Protect; }
+ /* + * Get or create a page operation descriptor + */ + PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.QuadPart, MM_PAGEOP_PAGEIN, FALSE); + if (PageOp == NULL) + { + DPRINT1("MmGetPageOp failed\n"); + ASSERT(FALSE); + } + + /* + * Check if someone else is already handling this fault, if so wait + * for them + */ + if (PageOp->Thread != PsGetCurrentThread()) + { + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + Status = MmspWaitForPageOpCompletionEvent(PageOp); + /* + * Check for various strange conditions + */ + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op, status = %x\n", Status); + ASSERT(FALSE); + } + if (PageOp->Status == STATUS_PENDING) + { + DPRINT1("Woke for page op before completion\n"); + ASSERT(FALSE); + } + MmLockAddressSpace(AddressSpace); + /* + * If this wasn't a pagein then restart the operation + */ + if (PageOp->OpType != MM_PAGEOP_PAGEIN) + { + MmspCompleteAndReleasePageOp(PageOp); + DPRINT("Address 0x%.8X\n", Address); + return(STATUS_MM_RESTART_OPERATION); + } + + /* + * If the thread handling this fault has failed then we don't retry + */ + if (!NT_SUCCESS(PageOp->Status)) + { + Status = PageOp->Status; + MmspCompleteAndReleasePageOp(PageOp); + DPRINT("Address 0x%.8X\n", Address); + return(Status); + } + MmLockSectionSegment(Segment); + /* + * If the completed fault was for another address space then set the + * page in this one. + */ + if (!MmIsPagePresent(Process, Address)) + { + DPRINT("!MmIsPagePresent(%p, %p)\n", Process, Address); + + Entry = MiGetPageEntrySectionSegment(Segment, &Offset); + HasSwapEntry = MmIsPageSwapEntry(Process, (PVOID)PAddress); + + if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry) + { + /* + * The page was a private page in another or in our address space + */ + MmUnlockSectionSegment(Segment); + MmspCompleteAndReleasePageOp(PageOp); + return(STATUS_MM_RESTART_OPERATION); + } + + Page = PFN_FROM_SSE(Entry); + + MmSharePageEntrySectionSegment(Segment, &Offset); + + /* FIXME: Should we call MmCreateVirtualMappingUnsafe if + * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true? + */ + Status = MmCreateVirtualMapping(Process, + Address, + Attributes, + &Page, + 1); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Unable to create virtual mapping\n"); + ASSERT(FALSE); + } + MmInsertRmap(Page, Process, (PVOID)PAddress); + } + if (Locked) + { + MmLockPage(Page); + } + MmUnlockSectionSegment(Segment); + PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); + DPRINT("Address 0x%.8X\n", Address); + return(STATUS_SUCCESS); + } + + /* + * Get the entry corresponding to the offset within the section + */ + Entry = MiGetPageEntrySectionSegment(Segment, &Offset); + if (Entry == 0) { + /* + * If the entry is zero (and it can't change because we have + * locked the segment) then we need to load the page. + */ + + /* + * Release all our locks and read in the page from disk + */ MmUnlockSectionSegment(Segment); - if (!Locked) - MmUnlockAddressSpace(AddressSpace); + MmUnlockAddressSpace(AddressSpace); + Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status); - if (!Locked) - MmLockAddressSpace(AddressSpace); - return Status; - } - - DPRINT("Allocated page %x\n", Page); + } Status = MmCreateVirtualMapping(Process, - PAddress, + Address, Attributes, &Page, 1); if (!NT_SUCCESS(Status)) { DPRINT1("Unable to create virtual mapping\n"); - MmReleasePageMemoryConsumer(MC_USER, Page); - DPRINT("Release page %x\n", Page); - if (!Locked) - MmLockAddressSpace(AddressSpace); - return Status; + ASSERT(FALSE); }
/* * Relock the address space and segment */ - if (!Locked) - MmLockAddressSpace(AddressSpace); - + MmLockAddressSpace(AddressSpace); MmLockSectionSegment(Segment); - if (Entry != MiGetPageEntrySectionSegment(Segment, &Offset)) - { - // Already handled - MmUnlockSectionSegment(Segment); - return STATUS_SUCCESS; - } + + /* + * Check the entry. No one should change the status of a page + * that has a pending page-in. + */ + Entry1 = MiGetPageEntrySectionSegment(Segment, &Offset); + if (Entry != Entry1) + { + DPRINT1("Someone changed ppte entry while we slept\n"); + ASSERT(FALSE); + } + /* * Mark the offset within the section as having valid, in-memory * data */ Entry = MAKE_SSE(Page << PAGE_SHIFT, 1); MiSetPageEntrySectionSegment(Segment, &Offset, Entry); + MmUnlockSectionSegment(Segment); + MmInsertRmap(Page, Process, (PVOID)PAddress);
if (Locked) { MmLockPage(Page); } - - MmUnlockSectionSegment(Segment); + PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); DPRINT("Address 0x%.8X\n", Address); return(STATUS_SUCCESS); } @@ -189,6 +302,8 @@ { MmLockPage(Page); } + PageOp->Status = Status; + MmspCompleteAndReleasePageOp(PageOp); return Status; } else @@ -218,6 +333,8 @@ { MmLockPage(Page); } + PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); DPRINT("Address 0x%.8X\n", Address); return(STATUS_SUCCESS); } @@ -292,7 +409,7 @@ } Section->Segment = Segment; Segment->ReferenceCount = 1; - KeInitializeGuardedMutex(&Segment->Lock); + ExInitializeFastMutex(&Segment->Lock); Segment->Protection = SectionPageProtection; Segment->RawLength.QuadPart = MaximumSize.QuadPart; Segment->Length.QuadPart = PAGE_ROUND_UP(MaximumSize.QuadPart); @@ -428,6 +545,8 @@ ASSERT(FALSE); } MmReleasePageMemoryConsumer(MC_USER, Page); + PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); } else if (!Context.WasDirty && Context.Private && SwapEntry != 0) @@ -443,6 +562,8 @@ ASSERT(FALSE); } MmReleasePageMemoryConsumer(MC_USER, Page); + PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); }
@@ -491,6 +612,8 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); } MmUnlockAddressSpace(AddressSpace); + PageOp->Status = STATUS_UNSUCCESSFUL; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_PAGEFILE_QUOTA); } } @@ -535,6 +658,8 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); } MmUnlockAddressSpace(AddressSpace); + PageOp->Status = STATUS_UNSUCCESSFUL; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_UNSUCCESSFUL); }
@@ -563,6 +688,8 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); }
+ PageOp->Status = STATUS_SUCCESS; + MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); }
@@ -572,6 +699,8 @@ PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty) { ULONG Entry; + PMM_PAGEOP PageOp; + NTSTATUS Status; LARGE_INTEGER Offset; PROS_SECTION_OBJECT Section; PMM_SECTION_SEGMENT Segment; @@ -588,6 +717,26 @@
Section = MemoryArea->Data.SectionData.Section; Segment = MemoryArea->Data.SectionData.Segment; + + PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.QuadPart); + + while (PageOp) + { + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + + Status = MmspWaitForPageOpCompletionEvent(PageOp); + if (Status != STATUS_SUCCESS) + { + DPRINT1("Failed to wait for page op, status = %x\n", Status); + ASSERT(FALSE); + } + + MmLockAddressSpace(AddressSpace); + MmLockSectionSegment(Segment); + MmspCompleteAndReleasePageOp(PageOp); + PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.QuadPart); + }
DPRINT("MmFreeSectionPage -> MmGetPageEntrySectionSegment(%p, %x)\n", Segment, Offset.u.LowPart); Entry = MiGetPageEntrySectionSegment(Segment, &Offset);