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/lazyr…
==============================================================================
--- 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/int…
==============================================================================
--- 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/de…
==============================================================================
--- 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/io…
==============================================================================
--- 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/ra…
==============================================================================
--- 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.…
==============================================================================
--- 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.…
==============================================================================
--- 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?re…
==============================================================================
--- 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?r…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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);