[ros-diffs] [arty] 44291: Revert my recent traffic for now. This needs to be approached differently. I'm going in the wrong direction in complexity terms.

arty at svn.reactos.org arty at svn.reactos.org
Fri Nov 27 02:03:24 CET 2009


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.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/lazyrite.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/internal/newmm.h?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/device.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/iofunc.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/rawfs.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- branches/arty-newcc/ntoskrnl/io/iomgr/rawfs.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/io/iomgr/rawfs.c [iso-8859-1] Fri Nov 27 02:03:24 2009
@@ -239,7 +239,6 @@
     else
     {
         /* Invalid create request */
-		DPRINT1("STATUS_INVALID_PARAMETER\n");
         Status = STATUS_INVALID_PARAMETER;
         Irp->IoStatus.Information = 0;
     }
@@ -436,7 +435,6 @@
         default:
 
             /* Fail */
-		DPRINT1("STATUS_INVALID_PARAMETER\n");
             Status = STATUS_INVALID_PARAMETER;
             break;
     }
@@ -578,7 +576,6 @@
             DeviceObject->AlignmentRequirement))
         {
             /* It's not, fail */
-		DPRINT1("STATUS_INVALID_PARAMETER\n");
             Status = STATUS_INVALID_PARAMETER;
         }
         else
@@ -851,7 +848,6 @@
         default:
 
             /* Fail it */
-		DPRINT1("STATUS_INVALID_PARAMETER\n");
             Status = STATUS_INVALID_PARAMETER;
             break;
     }

Modified: branches/arty-newcc/ntoskrnl/mm/anonmem.c
URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/anonmem.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/anonmem.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/anonmem.c [iso-8859-1] Fri Nov 27 02:03:24 2009
@@ -377,10 +377,13 @@
    /*
     * Try to allocate a page
     */
-   MmUnlockAddressSpace(AddressSpace);
-   Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
-   MmLockAddressSpace(AddressSpace);
-
+   Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
+   if (Status == STATUS_NO_MEMORY)
+   {
+      MmUnlockAddressSpace(AddressSpace);
+      Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+      MmLockAddressSpace(AddressSpace);
+   }
    if (!NT_SUCCESS(Status))
    {
       DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status);

Modified: branches/arty-newcc/ntoskrnl/mm/balance.c
URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/balance.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- branches/arty-newcc/ntoskrnl/mm/freelist.c [iso-8859-1] (original)
+++ branches/arty-newcc/ntoskrnl/mm/freelist.c [iso-8859-1] Fri Nov 27 02:03:24 2009
@@ -99,7 +99,6 @@
       return 0;
    }
    PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
-   MmReferencePage(PageDescriptor - MmPfnDatabase);
    ASSERT_PFN(PageDescriptor);
    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
    return PageDescriptor - MmPfnDatabase;
@@ -116,7 +115,7 @@
    Page = MiGetPfnEntry(Pfn);
    ASSERT(Page);
    ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED);
-   ASSERT(Page->Flags.Consumer == MC_USER || Page->Flags.Consumer == MC_PPOOL);
+   ASSERT(Page->Flags.Consumer == MC_USER);
    InsertTailList(&UserPageListHead, &Page->ListEntry);
    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
 }
@@ -134,17 +133,14 @@
    Page = MiGetPfnEntry(PreviousPfn);
    ASSERT(Page);
    ASSERT(Page->Flags.Type == MM_PHYSICAL_PAGE_USED);
-   ASSERT(Page->Flags.Consumer == MC_USER || Page->Flags.Consumer == MC_PPOOL);
+   ASSERT(Page->Flags.Consumer == MC_USER);
    NextListEntry = (PLIST_ENTRY)Page->ListEntry.Flink;
    if (NextListEntry == &UserPageListHead)
    {
-	  MmDereferencePage(PreviousPfn);
 	  KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
       return 0;
    }
    PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
-   MmReferencePage(PageDescriptor - MmPfnDatabase);
-   MmDereferencePage(PreviousPfn);
    KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
    return PageDescriptor - MmPfnDatabase;
 }
@@ -910,7 +906,6 @@
 NTAPI
 MmDereferencePage(PFN_TYPE Pfn)
 {
-   KIRQL oldIrql;
    PPHYSICAL_PAGE Page;
 
    DPRINT("MmDereferencePage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
@@ -933,12 +928,7 @@
    if (Page->ReferenceCount == 0)
    {
       MmAvailablePages++;
-      if (Page->Flags.Consumer == MC_USER)
-	  {
-		  oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
-		  RemoveEntryList(&Page->ListEntry);
-		  KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-	  }		  
+      if (Page->Flags.Consumer == MC_USER) RemoveEntryList(&Page->ListEntry);
       if (Page->RmapListHead != (LONG)NULL)
       {
          DPRINT1("Freeing page with rmap entries.\n");

Modified: branches/arty-newcc/ntoskrnl/mm/mpw.c
URL: http://svn.reactos.org/svn/reactos/branches/arty-newcc/ntoskrnl/mm/mpw.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/data.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/image.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/io.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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/pagefile.c?rev=44291&r1=44290&r2=44291&view=diff
==============================================================================
--- 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);




More information about the Ros-diffs mailing list