Author: arty Date: Thu Nov 26 23:50:50 2009 New Revision: 44290
URL: http://svn.reactos.org/svn/reactos?rev=44290&view=rev Log: Debug paths related to page reclamation and simplify balance to the core. Also remove some vestigal uses of PageOps.
Modified: 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/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/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] Thu Nov 26 23:50:50 2009 @@ -260,7 +260,7 @@
typedef struct _MM_SECTION_SEGMENT { - FAST_MUTEX Lock; /* lock which protects the page directory */ + KGUARDED_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,7 +1685,8 @@
NTSTATUS NTAPI -MiReadFilePage(PFILE_OBJECT FileObject, PLARGE_INTEGER Offset, PPFN_TYPE Page); +MiReadFilePage +(PFILE_OBJECT FileObject, PLARGE_INTEGER Offset, PPFN_TYPE Page, BOOLEAN Locked);
VOID NTAPI @@ -1743,11 +1744,15 @@
VOID NTAPI -MmLockSectionSegment(PMM_SECTION_SEGMENT Segment); - -VOID -NTAPI -MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment); +_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__)
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] Thu Nov 26 23:50:50 2009 @@ -1150,7 +1150,11 @@ NTSTATUS Status;
/* Make sure there's a VPB */ - if (!FileSystemDeviceObject->Vpb) return STATUS_INVALID_PARAMETER; + if (!FileSystemDeviceObject->Vpb) + { + DPRINT1("STATUS_INVALID_PARAMETER\n"); + return STATUS_INVALID_PARAMETER; + }
/* Acquire it */ IoAcquireVpbSpinLock(&OldIrql); @@ -1182,6 +1186,7 @@ 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] Thu Nov 26 23:50:50 2009 @@ -278,6 +278,7 @@ { /* Fail */ ObDereferenceObject(FileObject); + DPRINT1("STATUS_INVALID_PARAMETER\n"); return STATUS_INVALID_PARAMETER; }
@@ -1122,6 +1123,7 @@ /* Check if CompletionFilter is valid */ if (!CompletionFilter || (CompletionFilter & ~FILE_NOTIFY_VALID_MASK)) { + DPRINT1("STATUS_INVALID_PARAMETER\n"); return STATUS_INVALID_PARAMETER; } } @@ -2050,6 +2052,7 @@ /* 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; }
@@ -2424,6 +2427,7 @@ (FileObject->CompletionContext)) { /* Fail */ + DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; } else @@ -2458,6 +2462,7 @@ */ ExFreePool(Context); ObDereferenceObject(Queue); + DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; } } @@ -2903,6 +2908,7 @@ /* 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] Thu Nov 26 23:50:50 2009 @@ -239,6 +239,7 @@ else { /* Invalid create request */ + DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; Irp->IoStatus.Information = 0; } @@ -435,6 +436,7 @@ default:
/* Fail */ + DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; break; } @@ -576,6 +578,7 @@ DeviceObject->AlignmentRequirement)) { /* It's not, fail */ + DPRINT1("STATUS_INVALID_PARAMETER\n"); Status = STATUS_INVALID_PARAMETER; } else @@ -848,6 +851,7 @@ 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] Thu Nov 26 23:50:50 2009 @@ -377,13 +377,10 @@ /* * Try to allocate a page */ - Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page); - if (Status == STATUS_NO_MEMORY) - { - MmUnlockAddressSpace(AddressSpace); - Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); - MmLockAddressSpace(AddressSpace); - } + 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] Thu Nov 26 23:50:50 2009 @@ -32,18 +32,17 @@ /* GLOBALS ******************************************************************/
MM_MEMORY_CONSUMER MiMemoryConsumers[MC_MAXIMUM]; -static ULONG MiMinimumAvailablePages; +static ULONG MiMinimumAvailablePages = 512; static ULONG MiNrTotalPages; static LIST_ENTRY AllocationListHead; static KSPIN_LOCK AllocationListLock; -static ULONG MiPagesRequired = 0; -static ULONG MiMinimumPagesPerRun = 10; +static ULONG MiMinimumPagesPerRun = 128;
static CLIENT_ID MiBalancerThreadId; static HANDLE MiBalancerThreadHandle = NULL; static KEVENT MiBalancerEvent; +static KEVENT MiBalancerContinue; static KTIMER MiBalancerTimer; -static LONG MiBalancerWork = 0;
/* FUNCTIONS ****************************************************************/
@@ -67,7 +66,6 @@ MiNrTotalPages = NrAvailablePages;
/* Set up targets. */ - MiMinimumAvailablePages = 64; if ((NrAvailablePages + NrSystemPages) >= 8192) { MiMemoryConsumers[MC_CACHE].PagesTarget = NrAvailablePages / 4 * 3; @@ -117,7 +115,7 @@ if (MmGetReferenceCountPage(Page) == 1) { (void)InterlockedDecrementUL(&MiMemoryConsumers[Consumer].PagesUsed); - if (IsListEmpty(&AllocationListHead) || MmAvailablePages < MiMinimumAvailablePages) + if (IsListEmpty(&AllocationListHead)) { KeReleaseSpinLock(&AllocationListLock, OldIrql); OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); @@ -129,7 +127,8 @@ Entry = RemoveHeadList(&AllocationListHead); Request = CONTAINING_RECORD(Entry, MM_ALLOCATION_REQUEST, ListEntry); KeReleaseSpinLock(&AllocationListLock, OldIrql); - if(Consumer == MC_USER) MmRemoveLRUUserPage(Page); + if(Consumer == MC_USER || Consumer == MC_PPOOL) + MmRemoveLRUUserPage(Page); MiZeroPage(Page); Request->Page = Page; KeSetEvent(&Request->Event, IO_NO_INCREMENT, FALSE); @@ -142,26 +141,6 @@ }
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 @@ -172,27 +151,35 @@ 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); + MmRemoveLRUUserPage(CurrentPage); + MmInsertLRULastUserPage(CurrentPage); + return STATUS_SUCCESS; }
CurrentPage = NextPage; } + if (CurrentPage) + MmDereferencePage(CurrentPage); + + DPRINT("Done: %d\n", NrFreedPages); + return(STATUS_SUCCESS); }
@@ -205,14 +192,16 @@ ULONG NrFreedPages; NTSTATUS Status;
- Target = (MiMinimumAvailablePages - MmAvailablePages) + MiPagesRequired; + Target = (MiMinimumAvailablePages - MmAvailablePages); Target = max(Target, (LONG) MiMinimumPagesPerRun);
for (i = 0; i < MC_MAXIMUM && Target > 0; i++) { if (MiMemoryConsumers[i].Trim != NULL) { - Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages); + DPRINT("Trimming %d\n"); + Status = MiMemoryConsumers[i].Trim(Target, 0, &NrFreedPages); + DPRINT("Got %d pages\n", NrFreedPages); if (!NT_SUCCESS(Status)) { KeBugCheck(MEMORY_MANAGEMENT); @@ -226,7 +215,7 @@ MiIsBalancerThread(VOID) { return MiBalancerThreadHandle != NULL && - PsGetCurrentThread() == MiBalancerThreadId.UniqueThread; + PsGetCurrentThreadId() == MiBalancerThreadId.UniqueThread; }
NTSTATUS @@ -234,106 +223,67 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, PPFN_TYPE AllocatedPage) { - ULONG OldUsed; - PFN_TYPE Page; + PFN_TYPE Page = 0; KIRQL OldIrql;
- /* - * 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); + (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); }
/* * Allocate always memory for the non paged pool and for the pager thread. */ - if ((Consumer == MC_NPPOOL) || (Consumer == MC_SYSTEM) || MiIsBalancerThread()) + if ((Consumer == MC_NPPOOL) || + (Consumer == MC_SYSTEM) || + MiIsBalancerThread() || + (MmAvailablePages > MiMinimumAvailablePages)) { OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock); Page = MmAllocPage(Consumer, 0); KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql); - if (Page == 0) + if (!Page && MiIsBalancerThread()) { + DPRINT1("Can't allocate for balancer: %d vs %d\n", + MmAvailablePages, MiMinimumAvailablePages); 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. */ - 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); + 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); *AllocatedPage = Page; - + return(STATUS_SUCCESS); }
@@ -342,15 +292,11 @@ { 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) { @@ -363,61 +309,8 @@ NULL, NULL);
- 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); - } + MmRebalanceMemoryConsumers(); + KeSetEvent(&MiBalancerContinue, IO_NO_INCREMENT, FALSE); } }
@@ -437,6 +330,7 @@
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] Thu Nov 26 23:50:50 2009 @@ -116,7 +116,7 @@ Page = MiGetPfnEntry(Pfn); ASSERT(Page); ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED); - ASSERT(Page->Flags.Consumer == MC_USER); + ASSERT(Page->Flags.Consumer == MC_USER || Page->Flags.Consumer == MC_PPOOL); InsertTailList(&UserPageListHead, &Page->ListEntry); KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql); } @@ -134,7 +134,7 @@ Page = MiGetPfnEntry(PreviousPfn); ASSERT(Page); ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED); - ASSERT(Page->Flags.Consumer == MC_USER); + ASSERT(Page->Flags.Consumer == MC_USER || Page->Flags.Consumer == MC_PPOOL); NextListEntry = (PLIST_ENTRY)Page->ListEntry.Flink; if (NextListEntry == &UserPageListHead) {
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] Thu Nov 26 23:50:50 2009 @@ -17,7 +17,7 @@ /* GLOBALS *******************************************************************/
HANDLE MpwThreadHandle; -static CLIENT_ID MpwThreadId; +CLIENT_ID MpwThreadId; KEVENT MpwThreadEvent, MpwCompleteEvent; BOOLEAN MpwThreadShouldTerminate;
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] Thu Nov 26 23:50:50 2009 @@ -32,6 +32,7 @@
/* GLOBALS ******************************************************************/
+ULONG RmapPagingOut = 0; static FAST_MUTEX RmapListLock; static NPAGED_LOOKASIDE_LIST RmapLookasideList;
@@ -62,7 +63,7 @@ ULONG Type; PVOID Address; PEPROCESS Process; - PMM_PAGEOP PageOp; + PMM_PAGEOP PageOp = NULL; ULONG Offset; NTSTATUS Status = STATUS_SUCCESS;
@@ -121,6 +122,7 @@ { Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+#ifndef _NEWCC_ /* * Get or create a pageop */ @@ -137,6 +139,7 @@ } return(STATUS_UNSUCCESSFUL); } +#endif
/* * Release locks now we have a page op. @@ -205,7 +208,7 @@ ULONG Type; PVOID Address; PEPROCESS Process; - PMM_PAGEOP PageOp; + PMM_PAGEOP PageOp = NULL; ULONG Offset; NTSTATUS Status = STATUS_SUCCESS;
@@ -255,6 +258,7 @@ { Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+#ifndef _NEWCC_ /* * Get or create a pageop */ @@ -270,6 +274,7 @@ } return(STATUS_UNSUCCESSFUL); } +#endif
/* * Release locks now we have a page op. @@ -388,6 +393,8 @@ { PMM_RMAP_ENTRY current_entry;
+ ASSERT(Page); + ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); if (current_entry == NULL) @@ -409,6 +416,8 @@ { PMM_RMAP_ENTRY current_entry;
+ ASSERT(Page); + ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); if (current_entry == NULL) @@ -429,6 +438,8 @@ MmIsDirtyPageRmap(PFN_TYPE Page) { PMM_RMAP_ENTRY current_entry; + + ASSERT(Page);
ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); @@ -459,6 +470,7 @@ PMM_RMAP_ENTRY new_entry; ULONG PrevSize;
+ ASSERT(Page); Address = (PVOID)PAGE_ROUND_DOWN(Address);
new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList); @@ -530,6 +542,8 @@ PMM_RMAP_ENTRY previous_entry; PEPROCESS Process;
+ ASSERT(Page); + ExAcquireFastMutex(&RmapListLock); current_entry = MmGetRmapListHeadPage(Page); if (current_entry == NULL) @@ -567,6 +581,8 @@ 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] Thu Nov 26 23:50:50 2009 @@ -122,18 +122,18 @@
VOID NTAPI -MmLockSectionSegment(PMM_SECTION_SEGMENT Segment) -{ - DPRINT("MmLockSectionSegment(%p)\n", Segment); - ExAcquireFastMutex(&Segment->Lock); +_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line) +{ + DPRINT("MmLockSectionSegment(%p,%s:%d)\n", Segment, file, line); + KeAcquireGuardedMutex(&Segment->Lock); }
VOID NTAPI -MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment) -{ - ExReleaseFastMutex(&Segment->Lock); - DPRINT("MmUnlockSectionSegment(%p)\n", Segment); +_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line) +{ + DPRINT("MmUnlockSectionSegment(%p,%s:%d)\n", Segment, file, line); + KeReleaseGuardedMutex(&Segment->Lock); }
VOID @@ -233,7 +233,7 @@
NTSTATUS NTAPI -MiReadFilePage(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PPFN_TYPE Page) +MiReadFilePage(PFILE_OBJECT FileObject, PLARGE_INTEGER FileOffset, PPFN_TYPE Page, BOOLEAN Locked) { PFN_TYPE XPage; NTSTATUS Status; @@ -255,7 +255,8 @@ return Status; } - MmLockAddressSpace(MmGetKernelAddressSpace()); + if (!Locked) + MmLockAddressSpace(MmGetKernelAddressSpace()); Status = MmCreateMemoryArea (MmGetKernelAddressSpace(), MEMORY_AREA_VIRTUAL_MEMORY, @@ -271,7 +272,8 @@ if (!NT_SUCCESS(Status)) { DPRINT1("STATUS_NO_MEMORY: %x\n", Status); - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + if (!Locked) + MmUnlockAddressSpace(MmGetKernelAddressSpace()); MmReleasePageMemoryConsumer(MC_USER, *Page); return STATUS_NO_MEMORY; } @@ -280,13 +282,15 @@ if (!NT_SUCCESS(Status)) { MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + if (!Locked) + MmUnlockAddressSpace(MmGetKernelAddressSpace()); MmReleasePageMemoryConsumer(MC_USER, *Page); DPRINT1("Status: %x\n", Status); return Status; } - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + if (!Locked) + MmUnlockAddressSpace(MmGetKernelAddressSpace());
MiZeroPage(*Page); Status = MiSimpleRead @@ -298,11 +302,13 @@ DPRINT("Read Status %x (Page %x)\n", Status, *Page);
- MmLockAddressSpace(MmGetKernelAddressSpace()); + if (!Locked) + MmLockAddressSpace(MmGetKernelAddressSpace()); MmDeleteVirtualMapping(NULL, PageBuf, FALSE, NULL, &XPage); ASSERT(XPage == *Page); MmFreeMemoryArea(MmGetKernelAddressSpace(), TmpArea, NULL, NULL); - MmUnlockAddressSpace(MmGetKernelAddressSpace()); + if (!Locked) + MmUnlockAddressSpace(MmGetKernelAddressSpace());
if (!NT_SUCCESS(Status)) { @@ -377,9 +383,11 @@ DPRINT("Reading at offset %08x%08x (relative %x)\n", TotalOffset.HighPart, TotalOffset.LowPart, Offset); MmUnlockSectionSegment(Segment); - MmUnlockAddressSpace(AddressSpace); - Status = MiReadFilePage(Segment->FileObject, &TotalOffset, &Page); - MmLockAddressSpace(AddressSpace); + if (!Locked) + MmUnlockAddressSpace(AddressSpace); + Status = MiReadFilePage(Segment->FileObject, &TotalOffset, &Page, Locked); + if (!Locked) + MmLockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status)) { @@ -422,10 +430,23 @@ 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); @@ -434,6 +455,7 @@ DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status); ASSERT(FALSE); } + DPRINT("CreateVirtualMapping: %x -> %x\n", Address, Attributes); Status = MmCreateVirtualMapping(Process, Address, @@ -568,17 +590,20 @@ MiCopyFromUserPage(PFN_TYPE DestPage, PVOID SourceAddress) { PEPROCESS Process; - KIRQL Irql; + KIRQL PrimaryIrql, 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); }
@@ -657,7 +682,9 @@ /* * Allocate a page */ + MmUnlockSectionSegment(Segment); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &NewPage); + if (!NT_SUCCESS(Status)) { ASSERT(FALSE); @@ -668,6 +695,15 @@ * 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. @@ -834,26 +870,39 @@ ("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; - MmCreateVirtualMapping(NULL, Address, PAGE_READWRITE, &Page, 1); - MmInsertRmap(Page, NULL, Address); - MiSetPageEntrySectionSegment(Segment, &FileOffset, MAKE_SSE(Page << PAGE_SHIFT, 1)); + + 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); } FileOffset.QuadPart += PAGE_SIZE; } + MmUnlockSectionSegment(Segment); MmUnlockAddressSpace(AddressSpace); return STATUS_SUCCESS; @@ -1000,8 +1049,6 @@ }
MmReleasePageMemoryConsumer(MC_USER, Page); - PageOp->Status = STATUS_SUCCESS; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); } else if (!Context.WasDirty && Context.Private && SwapEntry != 0) @@ -1017,8 +1064,6 @@ ASSERT(FALSE); } MmReleasePageMemoryConsumer(MC_USER, Page); - PageOp->Status = STATUS_SUCCESS; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); }
@@ -1067,8 +1112,6 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); } MmUnlockAddressSpace(AddressSpace); - PageOp->Status = STATUS_UNSUCCESSFUL; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_PAGEFILE_QUOTA); } } @@ -1113,8 +1156,6 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); } MmUnlockAddressSpace(AddressSpace); - PageOp->Status = STATUS_UNSUCCESSFUL; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_UNSUCCESSFUL); }
@@ -1143,8 +1184,6 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); }
- PageOp->Status = STATUS_SUCCESS; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); }
@@ -1159,10 +1198,8 @@ PROS_SECTION_OBJECT Section; PMM_SECTION_SEGMENT Segment; PFN_TYPE Page; - SWAPENTRY SwapEntry; ULONG Entry; - BOOLEAN Private; - NTSTATUS Status; + NTSTATUS Status = STATUS_SUCCESS; PFILE_OBJECT FileObject; PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
@@ -1183,83 +1220,38 @@ /* * 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); - SwapEntry = MmGetSavedSwapEntryPage(Page); + + if (!Page) + { + // Somebody else already paged it out + MmUnlockSectionSegment(Segment); + MmUnlockAddressSpace(AddressSpace); + return STATUS_SUCCESS; + }
/* * Check for a private (COWed) page. */ - if (IS_SWAP_FROM_SSE(Entry) || PFN_FROM_SSE(Entry) != Page) - { - Private = TRUE; + 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); } else { - 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); + MmUnlockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); + } + + return(Status); }
NTSTATUS @@ -1291,8 +1283,6 @@ Segment = MemoryArea->Data.SectionData.Segment; ViewOffset.QuadPart = MemoryArea->Data.SectionData.ViewOffset.QuadPart;
- MmLockSectionSegment(Segment); - Pages = ExAllocatePool (NonPagedPool, sizeof(PFN_TYPE) * @@ -1302,6 +1292,8 @@ { ASSERT(FALSE); } + + MmLockSectionSegment(Segment);
for (PageAddress = BeginningAddress; PageAddress < EndingAddress; @@ -1336,8 +1328,10 @@ { 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 @@ -1695,7 +1689,7 @@ return(STATUS_NO_MEMORY); }
- ExInitializeFastMutex(&Segment->Lock); + KeInitializeGuardedMutex(&Segment->Lock);
Segment->ReferenceCount = 1; Section->Segment = Segment; @@ -1713,7 +1707,7 @@ /* * Set the lock before assigning the segment to the file object */ - ExAcquireFastMutex(&Segment->Lock); + KeAcquireGuardedMutex(&Segment->Lock);
DPRINT("Filling out Segment info (No previous data section)\n"); ObReferenceObject(FileObject);
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] Thu Nov 26 23:50:50 2009 @@ -233,14 +233,17 @@ 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); - MmUnlockAddressSpace(AddressSpace); - Status = MiReadFilePage(Section->FileObject, &TotalOffset, &Page); - MmLockAddressSpace(AddressSpace); + if (!Locked) + MmUnlockAddressSpace(AddressSpace); + Status = MiReadFilePage(Section->FileObject, &TotalOffset, &Page, Locked); + if (!Locked) + MmLockAddressSpace(AddressSpace);
if (!NT_SUCCESS(Status)) { @@ -282,10 +285,15 @@
MmDeletePageFileMapping(Process, (PVOID)PAddress, &SwapEntry);
+ MmUnlockSectionSegment(Segment); + if (!Locked) + MmUnlockAddressSpace(AddressSpace); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { - ASSERT(FALSE); + if (!Locked) + MmLockAddressSpace(AddressSpace); + return Status; } DPRINT("Allocated page %x\n", Page);
@@ -296,6 +304,14 @@ 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, @@ -335,16 +351,26 @@ */ if (Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { - MmUnlockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); + if (!Locked) + MmUnlockAddressSpace(AddressSpace); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { DPRINT("Status %x\n", Status); - MmUnlockSectionSegment(Segment); + if (!Locked) + MmLockAddressSpace(AddressSpace); return Status; } DPRINT("Allocated page %x\n", Page); - MmLockAddressSpace(AddressSpace); + if (!Locked) + MmLockAddressSpace(AddressSpace); + if (MmIsPagePresent(Process, Address)) + { + // Handled elsewhere + MmReleasePageMemoryConsumer(MC_USER, Page); + return STATUS_SUCCESS; + } Status = MmCreateVirtualMapping(Process, Address, Region->Protect, @@ -354,7 +380,6 @@ { MmReleasePageMemoryConsumer(MC_USER, Page); DPRINT("Release page %x\n", Page); - MmUnlockSectionSegment(Segment); return(Status); } MmInsertRmap(Page, Process, (PVOID)PAddress); @@ -366,7 +391,6 @@ /* * Cleanup and release locks */ - MmUnlockSectionSegment(Segment); //DPRINT("Address 0x%.8X\n", Address); return(STATUS_SUCCESS); } @@ -386,7 +410,9 @@ /* * Release all our locks and read in the page from disk */ - MmUnlockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); + if (!Locked) + MmUnlockAddressSpace(AddressSpace);
if (Offset.QuadPart >= PAGE_ROUND_UP(Segment->RawLength.QuadPart)) { @@ -394,8 +420,8 @@ if (!NT_SUCCESS(Status)) { DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status); - MmLockAddressSpace(AddressSpace); - MmUnlockSectionSegment(Segment); + if (!Locked) + MmLockAddressSpace(AddressSpace); return Status; } DPRINT("Allocated page %x\n", Page); @@ -409,8 +435,8 @@ DPRINT1("Unable to create virtual mapping\n"); MmReleasePageMemoryConsumer(MC_USER, Page); DPRINT("Release page %x\n", Page); - MmLockAddressSpace(AddressSpace); - MmUnlockSectionSegment(Segment); + if (!Locked) + MmLockAddressSpace(AddressSpace); return Status; } } @@ -426,8 +452,8 @@ DPRINT1("Unable to create virtual mapping\n"); MmReleasePageMemoryConsumer(MC_USER, Page); DPRINT("Release page %x\n", Page); - MmLockAddressSpace(AddressSpace); - MmUnlockSectionSegment(Segment); + if (!Locked) + MmLockAddressSpace(AddressSpace); return Status; }
@@ -437,12 +463,21 @@ /* * Relock the address space and segment */ - MmLockAddressSpace(AddressSpace); + if (!Locked) + 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);
@@ -497,6 +532,8 @@ //DPRINT("Address 0x%.8X\n", Address); return(STATUS_SUCCESS); } + + ASSERT(FALSE); }
NTSTATUS @@ -1400,7 +1437,7 @@ /* And finish their initialization */ for ( i = 0; i < ImageSectionObject->NrSegments; ++ i ) { - ExInitializeFastMutex(&ImageSectionObject->Segments[i].Lock); + KeInitializeGuardedMutex(&ImageSectionObject->Segments[i].Lock); ImageSectionObject->Segments[i].Flags = MM_IMAGE_SEGMENT; ImageSectionObject->Segments[i].ReferenceCount = 1; MiInitializeSectionPageTable(&ImageSectionObject->Segments[i]);
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] Thu Nov 26 23:50:50 2009 @@ -54,8 +54,6 @@ #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. @@ -428,82 +426,65 @@ ULONG Length, PFN_TYPE Page) { + PFN_TYPE XPage; NTSTATUS Status; - PVOID Hyperspace; IO_STATUS_BLOCK Iosb; - 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); + 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());
DPRINT("MiWriteBackPage(%wZ,%08x%08x)\n", &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart); Status = MiSimpleWrite (FileObject, FileOffset, - PageBuffer, + PageBuf, 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] Thu Nov 26 23:50:50 2009 @@ -123,13 +123,15 @@
if (Entry == 0) { - MmUnlockAddressSpace(AddressSpace); + MmUnlockSectionSegment(Segment); + if (!Locked) + MmUnlockAddressSpace(AddressSpace); Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page); if (!NT_SUCCESS(Status)) { DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status); - MmLockAddressSpace(AddressSpace); - MmUnlockSectionSegment(Segment); + if (!Locked) + MmLockAddressSpace(AddressSpace); return Status; }
@@ -144,16 +146,24 @@ DPRINT1("Unable to create virtual mapping\n"); MmReleasePageMemoryConsumer(MC_USER, Page); DPRINT("Release page %x\n", Page); - MmLockAddressSpace(AddressSpace); - MmUnlockSectionSegment(Segment); + if (!Locked) + MmLockAddressSpace(AddressSpace); return Status; }
/* * Relock the address space and segment */ - MmLockAddressSpace(AddressSpace); - + if (!Locked) + MmLockAddressSpace(AddressSpace); + + MmLockSectionSegment(Segment); + if (Entry != MiGetPageEntrySectionSegment(Segment, &Offset)) + { + // Already handled + MmUnlockSectionSegment(Segment); + return STATUS_SUCCESS; + } /* * Mark the offset within the section as having valid, in-memory * data @@ -282,7 +292,7 @@ } Section->Segment = Segment; Segment->ReferenceCount = 1; - ExInitializeFastMutex(&Segment->Lock); + KeInitializeGuardedMutex(&Segment->Lock); Segment->Protection = SectionPageProtection; Segment->RawLength.QuadPart = MaximumSize.QuadPart; Segment->Length.QuadPart = PAGE_ROUND_UP(MaximumSize.QuadPart); @@ -418,8 +428,6 @@ ASSERT(FALSE); } MmReleasePageMemoryConsumer(MC_USER, Page); - PageOp->Status = STATUS_SUCCESS; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); } else if (!Context.WasDirty && Context.Private && SwapEntry != 0) @@ -435,8 +443,6 @@ ASSERT(FALSE); } MmReleasePageMemoryConsumer(MC_USER, Page); - PageOp->Status = STATUS_SUCCESS; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); }
@@ -485,8 +491,6 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); } MmUnlockAddressSpace(AddressSpace); - PageOp->Status = STATUS_UNSUCCESSFUL; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_PAGEFILE_QUOTA); } } @@ -531,8 +535,6 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); } MmUnlockAddressSpace(AddressSpace); - PageOp->Status = STATUS_UNSUCCESSFUL; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_UNSUCCESSFUL); }
@@ -561,8 +563,6 @@ MiSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry); }
- PageOp->Status = STATUS_SUCCESS; - MmspCompleteAndReleasePageOp(PageOp); return(STATUS_SUCCESS); }