Patch of the Year.

Best regards,
Alex Ionescu


On Sat, Apr 28, 2012 at 10:56 AM, <arty@svn.reactos.org> wrote:
Author: arty
Date: Sat Apr 28 02:56:31 2012
New Revision: 56441

URL: http://svn.reactos.org/svn/reactos?rev=56441&view=rev
Log:
[NTOSKRNL]
Remove PAGEOPs and use the argument to pass relevant information where needed,
including generally a section page table entry or a PFN_NUMBER.

In its place, the code looks for an MM_WAIT_ENTRY in the appropriate place and
waits, returning STATUS_MM_RESTART_OPERATION.  Rather than copying the pagein
and CoW operations in the PAGEOP contention case, we just punt back and restart
the operation, resulting in simpler code.

Modified:
   trunk/reactos/ntoskrnl/CMakeLists.txt
   trunk/reactos/ntoskrnl/cache/section/sptab.c
   trunk/reactos/ntoskrnl/include/internal/mm.h
   trunk/reactos/ntoskrnl/mm/mminit.c
   trunk/reactos/ntoskrnl/mm/rmap.c
   trunk/reactos/ntoskrnl/mm/section.c

Modified: trunk/reactos/ntoskrnl/CMakeLists.txt
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/CMakeLists.txt?rev=56441&r1=56440&r2=56441&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/CMakeLists.txt [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/CMakeLists.txt [iso-8859-1] Sat Apr 28 02:56:31 2012
@@ -229,7 +229,6 @@
    mm/mmfault.c
    mm/mminit.c
    mm/pagefile.c
-    mm/pageop.c
    mm/region.c
    mm/rmap.c
    mm/section.c

Modified: trunk/reactos/ntoskrnl/cache/section/sptab.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cache/section/sptab.c?rev=56441&r1=56440&r2=56441&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/cache/section/sptab.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/cache/section/sptab.c [iso-8859-1] Sat Apr 28 02:56:31 2012
@@ -215,8 +215,9 @@
        ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry));
        MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
    } else if (IS_SWAP_FROM_SSE(Entry)) {
-        ASSERT(!IS_SWAP_FROM_SSE(OldEntry));
-        if (OldEntry)
+        ASSERT(!IS_SWAP_FROM_SSE(OldEntry) ||
+               SWAPENTRY_FROM_SSE(OldEntry) == MM_WAIT_ENTRY);
+        if (OldEntry && SWAPENTRY_FROM_SSE(OldEntry) != MM_WAIT_ENTRY)
            MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
    } else if (IS_SWAP_FROM_SSE(OldEntry)) {
        ASSERT(!IS_SWAP_FROM_SSE(Entry));

Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/mm.h?rev=56441&r1=56440&r2=56441&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Sat Apr 28 02:56:31 2012
@@ -49,7 +49,6 @@
 struct _KTRAP_FRAME;
 struct _EPROCESS;
 struct _MM_RMAP_ENTRY;
-struct _MM_PAGEOP;
 typedef ULONG_PTR SWAPENTRY;

 //
@@ -83,12 +82,6 @@
 #define MM_CORE_DUMP_TYPE_NONE              (0x0)
 #define MM_CORE_DUMP_TYPE_MINIMAL           (0x1)
 #define MM_CORE_DUMP_TYPE_FULL              (0x2)
-
-#define MM_PAGEOP_PAGEIN                    (1)
-#define MM_PAGEOP_PAGEOUT                   (2)
-#define MM_PAGEOP_PAGESYNCH                 (3)
-#define MM_PAGEOP_ACCESSFAULT               (4)
-#define MM_PAGEOP_CHANGEPROTECT             (5)

 /* Number of list heads to use */
 #define MI_FREE_POOL_LISTS 4
@@ -415,37 +408,6 @@
 extern MMPFNLIST MmModifiedPageListHead;
 extern MMPFNLIST MmModifiedNoWritePageListHead;

-typedef struct _MM_PAGEOP
-{
-  /* Type of operation. */
-  ULONG OpType;
-  /* Number of threads interested in this operation. */
-  ULONG ReferenceCount;
-  /* Event that will be set when the operation is completed. */
-  KEVENT CompletionEvent;
-  /* Status of the operation once it is completed. */
-  NTSTATUS Status;
-  /* TRUE if the operation was abandoned. */
-  BOOLEAN Abandoned;
-  /* The memory area to be affected by the operation. */
-  PMEMORY_AREA MArea;
-  ULONG Hash;
-  struct _MM_PAGEOP* Next;
-  struct _ETHREAD* Thread;
-  /*
-   * These fields are used to identify the operation if it is against a
-   * virtual memory area.
-   */
-  HANDLE Pid;
-  PVOID Address;
-  /*
-   * These fields are used to identify the operation if it is against a
-   * section mapping.
-   */
-  PMM_SECTION_SEGMENT Segment;
-  ULONGLONG Offset;
-} MM_PAGEOP, *PMM_PAGEOP;
-
 typedef struct _MM_MEMORY_CONSUMER
 {
    ULONG PagesUsed;
@@ -937,7 +899,7 @@
    PMMSUPPORT AddressSpace,
    PMEMORY_AREA MemoryArea,
    PVOID Address,
-    struct _MM_PAGEOP* PageOp
+    PFN_NUMBER Page
 );

 NTSTATUS
@@ -973,7 +935,7 @@
    PMMSUPPORT AddressSpace,
    PMEMORY_AREA MArea,
    PVOID Address,
-    PMM_PAGEOP PageOp
+    PFN_NUMBER Page
 );

 /* kmap.c ********************************************************************/
@@ -1006,38 +968,6 @@
 PVOID
 FASTCALL
 MmSafeReadPtr(PVOID Source);
-
-/* pageop.c ******************************************************************/
-
-VOID
-NTAPI
-MmReleasePageOp(PMM_PAGEOP PageOp);
-
-PMM_PAGEOP
-NTAPI
-MmGetPageOp(
-    PMEMORY_AREA MArea,
-    HANDLE Pid,
-    PVOID Address,
-    PMM_SECTION_SEGMENT Segment,
-    ULONGLONG Offset,
-    ULONG OpType,
-    BOOLEAN First
-);
-
-PMM_PAGEOP
-NTAPI
-MmCheckForPageOp(
-    PMEMORY_AREA MArea,
-    HANDLE Pid,
-    PVOID Address,
-    PMM_SECTION_SEGMENT Segment,
-    ULONGLONG Offset
-);
-
-VOID
-NTAPI
-MmInitializePageOp(VOID);

 /* process.c *****************************************************************/

@@ -1657,7 +1587,7 @@
    PMMSUPPORT AddressSpace,
    PMEMORY_AREA MemoryArea,
    PVOID Address,
-    struct _MM_PAGEOP *PageOp
+    ULONG_PTR Entry
 );

 NTSTATUS

Modified: trunk/reactos/ntoskrnl/mm/mminit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?rev=56441&r1=56440&r2=56441&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/mminit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/mminit.c [iso-8859-1] Sat Apr 28 02:56:31 2012
@@ -419,7 +419,6 @@
    MiInitializeUserPfnBitmap();
    MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
    MmInitializeRmapList();
-    MmInitializePageOp();
    MmInitSectionImplementation();
    MmInitPagingFile();


Modified: trunk/reactos/ntoskrnl/mm/rmap.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/rmap.c?rev=56441&r1=56440&r2=56441&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/rmap.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/rmap.c [iso-8859-1] Sat Apr 28 02:56:31 2012
@@ -52,7 +52,6 @@
   ULONG Type;
   PVOID Address;
   PEPROCESS Process;
-   PMM_PAGEOP PageOp;
   ULONGLONG Offset;
   NTSTATUS Status = STATUS_SUCCESS;

@@ -126,17 +125,20 @@
   Type = MemoryArea->Type;
   if (Type == MEMORY_AREA_SECTION_VIEW)
   {
+      ULONG Entry;
      Offset = MemoryArea->Data.SectionData.ViewOffset.QuadPart +
               ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress);
+
+      MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);

      /*
       * Get or create a pageop
       */
-      PageOp = MmGetPageOp(MemoryArea, NULL, 0,
-                           MemoryArea->Data.SectionData.Segment,
-                           Offset, MM_PAGEOP_PAGEOUT, TRUE);
-      if (PageOp == NULL)
-      {
+      Entry = MmGetPageEntrySectionSegment
+          (MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset);
+      if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
+      {
+         MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
         MmUnlockAddressSpace(AddressSpace);
         if (Address < MmSystemRangeStart)
         {
@@ -145,17 +147,19 @@
         }
         return(STATUS_UNSUCCESSFUL);
      }
+
+      MmSetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));

      /*
       * Release locks now we have a page op.
       */
+      MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
      MmUnlockAddressSpace(AddressSpace);

      /*
       * Do the actual page out work.
       */
-      Status = MmPageOutSectionView(AddressSpace, MemoryArea,
-                                    Address, PageOp);
+      Status = MmPageOutSectionView(AddressSpace, MemoryArea, Address, Entry);
   }
   else if (Type == MEMORY_AREA_CACHE)
   {

Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=56441&r1=56440&r2=56441&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Sat Apr 28 02:56:31 2012
@@ -127,6 +127,7 @@
   BOOLEAN WasDirty;
   BOOLEAN Private;
   PEPROCESS CallingProcess;
+   ULONG_PTR SectionEntry;
 }
 MM_SECTION_PAGEOUT_CONTEXT;

@@ -704,43 +705,6 @@
    return nStatus;
 }

-/* Note: Mmsp prefix denotes "Memory Manager Section Private". */
-
-/*
- * FUNCTION:  Waits in kernel mode up to ten seconds for an MM_PAGEOP event.
- * ARGUMENTS: PMM_PAGEOP which event we should wait for.
- * RETURNS:   Status of the wait.
- */
-static NTSTATUS
-MmspWaitForPageOpCompletionEvent(PMM_PAGEOP PageOp)
-{
-   LARGE_INTEGER Timeout;
-#ifdef __GNUC__ /* TODO: Use other macro to check for suffix to use? */
-
-   Timeout.QuadPart = -100000000LL; // 10 sec
-#else
-
-   Timeout.QuadPart = -100000000; // 10 sec
-#endif
-
-   return KeWaitForSingleObject(&PageOp->CompletionEvent, 0, KernelMode, FALSE, &Timeout);
-}
-
-
-/*
- * FUNCTION:  Sets the page op completion event and releases the page op.
- * ARGUMENTS: PMM_PAGEOP.
- * RETURNS:   In shorter time than it takes you to even read this
- *            description, so don't even think about geting a mug of coffee.
- */
-static void
-MmspCompleteAndReleasePageOp(PMM_PAGEOP PageOp)
-{
-   KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
-   MmReleasePageOp(PageOp);
-}
-
-
 /*
 * FUNCTION:  Waits in kernel mode indefinitely for a file object lock.
 * ARGUMENTS: PFILE_OBJECT to wait for.
@@ -831,12 +795,12 @@
                                 PMM_SECTION_SEGMENT Segment,
                                 PLARGE_INTEGER Offset,
                                 BOOLEAN Dirty,
-                                 BOOLEAN PageOut)
-{
-   ULONG_PTR Entry;
+                                 BOOLEAN PageOut,
+                                 ULONG_PTR *InEntry)
+{
+   ULONG_PTR Entry = InEntry ? *InEntry : MmGetPageEntrySectionSegment(Segment, Offset);
   BOOLEAN IsDirectMapped = FALSE;

-   Entry = MmGetPageEntrySectionSegment(Segment, Offset);
   if (Entry == 0)
   {
      DPRINT1("Entry == 0 for MmUnsharePageEntrySectionSegment\n");
@@ -844,7 +808,7 @@
   }
   if (SHARE_COUNT_FROM_SSE(Entry) == 0)
   {
-      DPRINT1("Zero share count for unshare\n");
+       DPRINT1("Zero share count for unshare (Seg %p Offset %x Page %x)\n", Segment, Offset->LowPart, PFN_FROM_SSE(Entry));
       KeBugCheck(MEMORY_MANAGEMENT);
   }
   if (IS_SWAP_FROM_SSE(Entry))
@@ -913,10 +877,14 @@
             *   page without a rmap entry.
             */
            MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+            if (InEntry) *InEntry = Entry;
+            MiSetPageEvent(NULL, NULL);
         }
         else
         {
            MmSetPageEntrySectionSegment(Segment, Offset, 0);
+            if (InEntry) *InEntry = 0;
+            MiSetPageEvent(NULL, NULL);
            if (!IsDirectMapped)
            {
               MmReleasePageMemoryConsumer(MC_USER, Page);
@@ -946,7 +914,9 @@
                  }
               }
               MmSetPageEntrySectionSegment(Segment, Offset, MAKE_SWAP_SSE(SavedSwapEntry));
+               if (InEntry) *InEntry = MAKE_SWAP_SSE(SavedSwapEntry);
               MmSetSavedSwapEntryPage(Page, 0);
+               MiSetPageEvent(NULL, NULL);
            }
            MmReleasePageMemoryConsumer(MC_USER, Page);
         }
@@ -959,7 +929,10 @@
   }
   else
   {
-      MmSetPageEntrySectionSegment(Segment, Offset, Entry);
+      if (InEntry)
+          *InEntry = Entry;
+      else
+          MmSetPageEntrySectionSegment(Segment, Offset, Entry);
   }
   return(SHARE_COUNT_FROM_SSE(Entry) > 0);
 }
@@ -1232,7 +1205,6 @@
   ULONG_PTR Entry;
   ULONG_PTR Entry1;
   ULONG Attributes;
-   PMM_PAGEOP PageOp;
   PMM_REGION Region;
   BOOLEAN HasSwapEntry;
   PVOID PAddress;
@@ -1270,7 +1242,7 @@
    * Lock the segment
    */
   MmLockSectionSegment(Segment);
-
+   Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
   /*
    * Check if this page needs to be mapped COW
    */
@@ -1286,111 +1258,41 @@
   }

   /*
-    * Get or create a page operation descriptor
-    */
-   PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart, MM_PAGEOP_PAGEIN, FALSE);
-   if (PageOp == NULL)
-   {
-      DPRINT1("MmGetPageOp failed\n");
-       KeBugCheck(MEMORY_MANAGEMENT);
-   }
-
-   /*
    * Check if someone else is already handling this fault, if so wait
    * for them
    */
-   if (PageOp->Thread != PsGetCurrentThread())
+   if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
   {
      MmUnlockSectionSegment(Segment);
      MmUnlockAddressSpace(AddressSpace);
-      Status = MmspWaitForPageOpCompletionEvent(PageOp);
+      MiWaitForPageEvent(NULL, NULL);
+      MmLockAddressSpace(AddressSpace);
+      DPRINT("Address 0x%.8X\n", Address);
+      return(STATUS_MM_RESTART_OPERATION);
+   }
+
+   HasSwapEntry = MmIsPageSwapEntry(Process, Address);
+
+   if (HasSwapEntry)
+   {
+      SWAPENTRY SwapEntry;
      /*
-       * Check for various strange conditions
+       * Is it a wait entry?
       */
-      if (Status != STATUS_SUCCESS)
-      {
-         DPRINT1("Failed to wait for page op, status = %x\n", Status);
-          KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      if (PageOp->Status == STATUS_PENDING)
-      {
-         DPRINT1("Woke for page op before completion\n");
-          KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      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))
-      {
-         Entry = MmGetPageEntrySectionSegment(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,
-                                         PAddress,
-                                         Attributes,
-                                         &Page,
-                                         1);
-         if (!NT_SUCCESS(Status))
-         {
-            DPRINT1("Unable to create virtual mapping\n");
-            KeBugCheck(MEMORY_MANAGEMENT);
-         }
-         MmInsertRmap(Page, Process, Address);
-      }
-      MmUnlockSectionSegment(Segment);
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
-      DPRINT("Address 0x%.8X\n", Address);
-      return(STATUS_SUCCESS);
-   }
-
-   HasSwapEntry = MmIsPageSwapEntry(Process, Address);
-   if (HasSwapEntry)
-   {
+      MmGetPageFileMapping(Process, Address, &SwapEntry);
+
+      if (SwapEntry == MM_WAIT_ENTRY)
+      {
+         MmUnlockSectionSegment(Segment);
+         MmUnlockAddressSpace(AddressSpace);
+         MiWaitForPageEvent(NULL, NULL);
+         MmLockAddressSpace(AddressSpace);
+         return STATUS_MM_RESTART_OPERATION;
+      }
+
      /*
       * Must be private page we have swapped out.
       */
-      SWAPENTRY SwapEntry;

      /*
       * Sanity check
@@ -1445,8 +1347,7 @@
      /*
       * Finish the operation
       */
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(Process, Address);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }
@@ -1476,8 +1377,7 @@
      /*
       * Cleanup and release locks
       */
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(Process, Address);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }
@@ -1518,8 +1418,7 @@
      /*
       * Cleanup and release locks
       */
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(Process, Address);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }
@@ -1539,6 +1438,7 @@
      /*
       * Release all our locks and read in the page from disk
       */
+      MmSetPageEntrySectionSegment(Segment, &Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
      MmUnlockSectionSegment(Segment);
      MmUnlockAddressSpace(AddressSpace);

@@ -1573,11 +1473,64 @@
          * Cleanup and release locks
          */
         MmLockAddressSpace(AddressSpace);
-         PageOp->Status = Status;
-         MmspCompleteAndReleasePageOp(PageOp);
+         MiSetPageEvent(Process, Address);
         DPRINT("Address 0x%.8X\n", Address);
         return(Status);
      }
+
+      /*
+       * Mark the offset within the section as having valid, in-memory
+       * data
+       */
+      MmLockAddressSpace(AddressSpace);
+      MmLockSectionSegment(Segment);
+      Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
+      MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
+      MmUnlockSectionSegment(Segment);
+
+      Status = MmCreateVirtualMapping(Process,
+                                      PAddress,
+                                      Attributes,
+                                      &Page,
+                                      1);
+      if (!NT_SUCCESS(Status))
+      {
+         DPRINT1("Unable to create virtual mapping\n");
+          KeBugCheck(MEMORY_MANAGEMENT);
+      }
+      MmInsertRmap(Page, Process, Address);
+
+      MiSetPageEvent(Process, Address);
+      DPRINT("Address 0x%.8X\n", Address);
+      return(STATUS_SUCCESS);
+   }
+   else if (IS_SWAP_FROM_SSE(Entry))
+   {
+      SWAPENTRY SwapEntry;
+
+      SwapEntry = SWAPENTRY_FROM_SSE(Entry);
+
+      /*
+      * Release all our locks and read in the page from disk
+      */
+      MmUnlockSectionSegment(Segment);
+
+      MmUnlockAddressSpace(AddressSpace);
+      MI_SET_USAGE(MI_USAGE_SECTION);
+      if (Process) MI_SET_PROCESS2(Process->ImageFileName);
+      if (!Process) MI_SET_PROCESS2("Kernel Section");
+      Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
+      if (!NT_SUCCESS(Status))
+      {
+          KeBugCheck(MEMORY_MANAGEMENT);
+      }
+
+      Status = MmReadFromSwapPage(SwapEntry, Page);
+      if (!NT_SUCCESS(Status))
+      {
+          KeBugCheck(MEMORY_MANAGEMENT);
+      }
+
      /*
       * Relock the address space and segment
       */
@@ -1591,76 +1544,7 @@
      Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
      if (Entry != Entry1)
      {
-         DPRINT1("Someone changed ppte entry while we slept\n");
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
-
-      /*
-       * Mark the offset within the section as having valid, in-memory
-       * data
-       */
-      Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
-      MmSetPageEntrySectionSegment(Segment, &Offset, Entry);
-      MmUnlockSectionSegment(Segment);
-
-      Status = MmCreateVirtualMapping(Process,
-                                      PAddress,
-                                      Attributes,
-                                      &Page,
-                                      1);
-      if (!NT_SUCCESS(Status))
-      {
-         DPRINT1("Unable to create virtual mapping\n");
-          KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      MmInsertRmap(Page, Process, Address);
-
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
-      DPRINT("Address 0x%.8X\n", Address);
-      return(STATUS_SUCCESS);
-   }
-   else if (IS_SWAP_FROM_SSE(Entry))
-   {
-      SWAPENTRY SwapEntry;
-
-      SwapEntry = SWAPENTRY_FROM_SSE(Entry);
-
-      /*
-      * Release all our locks and read in the page from disk
-      */
-      MmUnlockSectionSegment(Segment);
-
-      MmUnlockAddressSpace(AddressSpace);
-      MI_SET_USAGE(MI_USAGE_SECTION);
-      if (Process) MI_SET_PROCESS2(Process->ImageFileName);
-      if (!Process) MI_SET_PROCESS2("Kernel Section");
-      Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
-      if (!NT_SUCCESS(Status))
-      {
-          KeBugCheck(MEMORY_MANAGEMENT);
-      }
-
-      Status = MmReadFromSwapPage(SwapEntry, Page);
-      if (!NT_SUCCESS(Status))
-      {
-          KeBugCheck(MEMORY_MANAGEMENT);
-      }
-
-      /*
-       * Relock the address space and segment
-       */
-      MmLockAddressSpace(AddressSpace);
-      MmLockSectionSegment(Segment);
-
-      /*
-       * Check the entry. No one should change the status of a page
-       * that has a pending page-in.
-       */
-      Entry1 = MmGetPageEntrySectionSegment(Segment, &Offset);
-      if (Entry != Entry1)
-      {
-         DPRINT1("Someone changed ppte entry while we slept\n");
+          DPRINT1("Someone changed ppte entry while we slept (%x vs %x)\n", Entry, Entry1);
          KeBugCheck(MEMORY_MANAGEMENT);
      }

@@ -1687,8 +1571,7 @@
          KeBugCheck(MEMORY_MANAGEMENT);
      }
      MmInsertRmap(Page, Process, Address);
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(Process, Address);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }
@@ -1715,8 +1598,7 @@
          KeBugCheck(MEMORY_MANAGEMENT);
      }
      MmInsertRmap(Page, Process, Address);
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(Process, Address);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }
@@ -1735,7 +1617,6 @@
   NTSTATUS Status;
   PVOID PAddress;
   LARGE_INTEGER Offset;
-   PMM_PAGEOP PageOp;
   PMM_REGION Region;
   ULONG_PTR Entry;
   PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
@@ -1799,46 +1680,29 @@
   /*
    * Get or create a pageop
    */
-   PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset.LowPart,
-                        MM_PAGEOP_ACCESSFAULT, FALSE);
-   if (PageOp == NULL)
-   {
-      DPRINT1("MmGetPageOp failed\n");
-       KeBugCheck(MEMORY_MANAGEMENT);
-   }
-
+   MmLockSectionSegment(Segment);
+   Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+
   /*
    * Wait for any other operations to complete
    */
-   if (PageOp->Thread != PsGetCurrentThread())
-   {
-      MmUnlockAddressSpace(AddressSpace);
-      Status = MmspWaitForPageOpCompletionEvent(PageOp);
-      /*
-      * Check for various strange conditions
-      */
-      if (Status == STATUS_TIMEOUT)
-      {
-         DPRINT1("Failed to wait for page op, status = %x\n", Status);
-          KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      if (PageOp->Status == STATUS_PENDING)
-      {
-         DPRINT1("Woke for page op before completion\n");
-          KeBugCheck(MEMORY_MANAGEMENT);
-      }
-      /*
-      * Restart the operation
-      */
-      MmLockAddressSpace(AddressSpace);
-      MmspCompleteAndReleasePageOp(PageOp);
-      DPRINT("Address 0x%.8X\n", Address);
-      return(STATUS_MM_RESTART_OPERATION);
+   if (Entry == SWAPENTRY_FROM_SSE(MM_WAIT_ENTRY))
+   {
+       MmUnlockSectionSegment(Segment);
+       MmUnlockAddressSpace(AddressSpace);
+       MiWaitForPageEvent(NULL, NULL);
+       /*
+        * Restart the operation
+        */
+       MmLockAddressSpace(AddressSpace);
+       DPRINT("Address 0x%.8X\n", Address);
+       return(STATUS_MM_RESTART_OPERATION);
   }

   /*
    * Release locks now we have the pageop
    */
+   MmUnlockSectionSegment(Segment);
   MmUnlockAddressSpace(AddressSpace);

   /*
@@ -1890,11 +1754,10 @@
   MmDeleteRmap(OldPage, Process, PAddress);
   MmInsertRmap(NewPage, Process, PAddress);
   MmLockSectionSegment(Segment);
-   MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE);
+   MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, NULL);
   MmUnlockSectionSegment(Segment);

-   PageOp->Status = STATUS_SUCCESS;
-   MmspCompleteAndReleasePageOp(PageOp);
+   MiSetPageEvent(Process, Address);
   DPRINT("Address 0x%.8X\n", Address);
   return(STATUS_SUCCESS);
 }
@@ -1904,7 +1767,7 @@
 {
   MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
   BOOLEAN WasDirty;
-   PFN_NUMBER Page;
+   PFN_NUMBER Page = 0;

   PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
   if (Process)
@@ -1928,7 +1791,8 @@
                                       PageOutContext->Segment,
                                       &PageOutContext->Offset,
                                       PageOutContext->WasDirty,
-                                       TRUE);
+                                       TRUE,
+                                       &PageOutContext->SectionEntry);
      MmUnlockSectionSegment(PageOutContext->Segment);
   }
   if (Process)
@@ -1940,21 +1804,17 @@
   {
      MmReleasePageMemoryConsumer(MC_USER, Page);
   }
-
-   DPRINT("PhysicalAddress %x, Address %x\n", Page << PAGE_SHIFT, Address);
 }

 NTSTATUS
 NTAPI
 MmPageOutSectionView(PMMSUPPORT AddressSpace,
                     MEMORY_AREA* MemoryArea,
-                     PVOID Address,
-                     PMM_PAGEOP PageOp)
+                     PVOID Address, ULONG_PTR Entry)
 {
   PFN_NUMBER Page;
   MM_SECTION_PAGEOUT_CONTEXT Context;
   SWAPENTRY SwapEntry;
-   ULONG_PTR Entry;
   ULONGLONG FileOffset;
   NTSTATUS Status;
   PFILE_OBJECT FileObject;
@@ -1973,6 +1833,7 @@
    */
   Context.Segment = MemoryArea->Data.SectionData.Segment;
   Context.Section = MemoryArea->Data.SectionData.Section;
+   Context.SectionEntry = Entry;
   Context.CallingProcess = Process;

   Context.Offset.QuadPart = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress
@@ -1983,6 +1844,8 @@

   FileObject = Context.Section->FileObject;
   DirectMapped = FALSE;
+
+   MmLockSectionSegment(Context.Segment);

 #ifndef NEWCC
   if (FileObject != NULL &&
@@ -2035,16 +1898,14 @@
   {
       DPRINT("Cannot page out locked section page: 0x%p (RefCount: %d)\n",
               Page, MmGetReferenceCountPage(Page));
-       PageOp->Status = STATUS_UNSUCCESSFUL;
-       MmspCompleteAndReleasePageOp(PageOp);
+       MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
+       MmUnlockSectionSegment(Context.Segment);
       return STATUS_UNSUCCESSFUL;
   }

   /*
    * Prepare the context structure for the rmap delete call.
    */
-   MmLockSectionSegment(Context.Segment);
-   Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
   MmUnlockSectionSegment(Context.Segment);
   Context.WasDirty = FALSE;
   if (Context.Segment->Image.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ||
@@ -2077,9 +1938,12 @@
   }

   MmDeleteAllRmaps(Page, (PVOID)&Context, MmPageOutDeleteMapping);
-   MmLockSectionSegment(Context.Segment);
-   Entry = MmGetPageEntrySectionSegment(Context.Segment, &Context.Offset);
-   MmUnlockSectionSegment(Context.Segment);
+
+   /* Since we passed in a surrogate, we'll get back the page entry
+    * state in our context.  This is intended to make intermediate
+    * decrements of share count not release the wait entry.
+    */
+   Entry = Context.SectionEntry;

   /*
    * If this wasn't a private page then we should have reduced the entry to
@@ -2117,8 +1981,7 @@
         MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
         MmUnlockSectionSegment(Context.Segment);
         MmReleasePageMemoryConsumer(MC_USER, Page);
-         PageOp->Status = STATUS_SUCCESS;
-         MmspCompleteAndReleasePageOp(PageOp);
+         MiSetPageEvent(NULL, NULL);
         return(STATUS_SUCCESS);
      }
   }
@@ -2140,8 +2003,7 @@
            MmUnlockSectionSegment(Context.Segment);
         }
         MmReleasePageMemoryConsumer(MC_USER, Page);
-         PageOp->Status = STATUS_SUCCESS;
-         MmspCompleteAndReleasePageOp(PageOp);
+         MiSetPageEvent(NULL, NULL);
         return(STATUS_SUCCESS);
      }
   }
@@ -2165,8 +2027,7 @@
         KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Bcb, (ULONG_PTR)FileOffset, (ULONG_PTR)Address);
      }
 #endif
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(NULL, NULL);
      return(STATUS_SUCCESS);
   }
   else if (!Context.WasDirty && !DirectMapped && !Context.Private)
@@ -2178,13 +2039,12 @@
         KeBugCheckEx(MEMORY_MANAGEMENT, SwapEntry, Page, (ULONG_PTR)Process, (ULONG_PTR)Address);
      }
      MmReleasePageMemoryConsumer(MC_USER, Page);
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(NULL, NULL);
      return(STATUS_SUCCESS);
   }
   else if (!Context.WasDirty && Context.Private && SwapEntry != 0)
   {
-      DPRINT1("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
+      DPRINT("Not dirty and private and not swapped (%p:%p)\n", Process, Address);
      MmSetSavedSwapEntryPage(Page, 0);
      MmLockAddressSpace(AddressSpace);
      Status = MmCreatePageFileMapping(Process,
@@ -2197,8 +2057,7 @@
         KeBugCheckEx(MEMORY_MANAGEMENT, Status, (ULONG_PTR)Process, (ULONG_PTR)Address, SwapEntry);
      }
      MmReleasePageMemoryConsumer(MC_USER, Page);
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(NULL, NULL);
      return(STATUS_SUCCESS);
   }

@@ -2253,8 +2112,7 @@
           MmUnlockSectionSegment(Context.Segment);
         }
         MmUnlockAddressSpace(AddressSpace);
-         PageOp->Status = STATUS_UNSUCCESSFUL;
-         MmspCompleteAndReleasePageOp(PageOp);
+         MiSetPageEvent(NULL, NULL);
         return(STATUS_PAGEFILE_QUOTA);
      }
   }
@@ -2299,8 +2157,7 @@
         MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
      }
      MmUnlockAddressSpace(AddressSpace);
-      PageOp->Status = STATUS_UNSUCCESSFUL;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(NULL, NULL);
      return(STATUS_UNSUCCESSFUL);
   }

@@ -2308,12 +2165,13 @@
    * Otherwise we have succeeded.
    */
   DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
-   MmLockSectionSegment(Context.Segment);
   MmSetSavedSwapEntryPage(Page, 0);
   if (Context.Segment->Flags & MM_PAGEFILE_SEGMENT ||
         Context.Segment->Image.Characteristics & IMAGE_SCN_MEM_SHARED)
   {
+      MmLockSectionSegment(Context.Segment);
      MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, MAKE_SWAP_SSE(SwapEntry));
+      MmUnlockSectionSegment(Context.Segment);
   }
   else
   {
@@ -2323,9 +2181,11 @@
   if (Context.Private)
   {
      MmLockAddressSpace(AddressSpace);
+      MmLockSectionSegment(Context.Segment);
      Status = MmCreatePageFileMapping(Process,
                                       Address,
                                       SwapEntry);
+      MmUnlockSectionSegment(Context.Segment);
      MmUnlockAddressSpace(AddressSpace);
      if (!NT_SUCCESS(Status))
      {
@@ -2335,13 +2195,15 @@
   }
   else
   {
+      MmLockAddressSpace(AddressSpace);
+      MmLockSectionSegment(Context.Segment);
      Entry = MAKE_SWAP_SSE(SwapEntry);
      MmSetPageEntrySectionSegment(Context.Segment, &Context.Offset, Entry);
-   }
-
-   MmUnlockSectionSegment(Context.Segment);
-   PageOp->Status = STATUS_SUCCESS;
-   MmspCompleteAndReleasePageOp(PageOp);
+      MmUnlockSectionSegment(Context.Segment);
+      MmUnlockAddressSpace(AddressSpace);
+   }
+
+   MiSetPageEvent(NULL, NULL);
   return(STATUS_SUCCESS);
 }

@@ -2350,7 +2212,7 @@
 MmWritePageSectionView(PMMSUPPORT AddressSpace,
                       PMEMORY_AREA MemoryArea,
                       PVOID Address,
-                       PMM_PAGEOP PageOp)
+                       ULONG PageEntry)
 {
   LARGE_INTEGER Offset;
   PROS_SECTION_OBJECT Section;
@@ -2447,12 +2309,16 @@
    */
   if (DirectMapped && !Private)
   {
+      LARGE_INTEGER SOffset;
      ASSERT(SwapEntry == 0);
+      SOffset.QuadPart = Offset.QuadPart + Segment->Image.FileOffset;
 #ifndef NEWCC
-      CcRosMarkDirtyCacheSegment(Bcb, (ULONG)(Offset.QuadPart + Segment->Image.FileOffset));
+      CcRosMarkDirtyCacheSegment(Bcb, Offset.LowPart);
 #endif
-      PageOp->Status = STATUS_SUCCESS;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MmLockSectionSegment(Segment);
+      MmSetPageEntrySectionSegment(Segment, &Offset, PageEntry);
+      MmUnlockSectionSegment(Segment);
+      MiSetPageEvent(NULL, NULL);
      return(STATUS_SUCCESS);
   }

@@ -2465,8 +2331,7 @@
      if (SwapEntry == 0)
      {
         MmSetDirtyAllRmaps(Page);
-         PageOp->Status = STATUS_UNSUCCESSFUL;
-         MmspCompleteAndReleasePageOp(PageOp);
+         MiSetPageEvent(NULL, NULL);
         return(STATUS_PAGEFILE_QUOTA);
      }
      MmSetSavedSwapEntryPage(Page, SwapEntry);
@@ -2481,8 +2346,7 @@
      DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n",
              Status);
      MmSetDirtyAllRmaps(Page);
-      PageOp->Status = STATUS_UNSUCCESSFUL;
-      MmspCompleteAndReleasePageOp(PageOp);
+      MiSetPageEvent(NULL, NULL);
      return(STATUS_UNSUCCESSFUL);
   }

@@ -2490,8 +2354,7 @@
    * Otherwise we have succeeded.
    */
   DPRINT("MM: Wrote section page 0x%.8X to swap!\n", Page << PAGE_SHIFT);
-   PageOp->Status = STATUS_SUCCESS;
-   MmspCompleteAndReleasePageOp(PageOp);
+   MiSetPageEvent(NULL, NULL);
   return(STATUS_SUCCESS);
 }

@@ -4039,8 +3902,6 @@
   PBCB Bcb;
   LARGE_INTEGER Offset;
   SWAPENTRY SavedSwapEntry;
-   PMM_PAGEOP PageOp;
-   NTSTATUS Status;
   PROS_SECTION_OBJECT Section;
   PMM_SECTION_SEGMENT Segment;
   PMMSUPPORT AddressSpace;
@@ -4057,27 +3918,18 @@
   Section = MemoryArea->Data.SectionData.Section;
   Segment = MemoryArea->Data.SectionData.Segment;

-   PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart);
-
-   while (PageOp)
+   Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+   while (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
   {
      MmUnlockSectionSegment(Segment);
      MmUnlockAddressSpace(AddressSpace);

-      Status = MmspWaitForPageOpCompletionEvent(PageOp);
-      if (Status != STATUS_SUCCESS)
-      {
-         DPRINT1("Failed to wait for page op, status = %x\n", Status);
-         KeBugCheck(MEMORY_MANAGEMENT);
-      }
+      MiWaitForPageEvent(NULL, NULL);

      MmLockAddressSpace(AddressSpace);
      MmLockSectionSegment(Segment);
-      MmspCompleteAndReleasePageOp(PageOp);
-      PageOp = MmCheckForPageOp(MemoryArea, NULL, NULL, Segment, Offset.LowPart);
-   }
-
-   Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+      Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+   }

   /*
    * For a dirty, datafile, non-private page mark it as dirty in the
@@ -4136,7 +3988,7 @@
      else
      {
         MmDeleteRmap(Page, Process, Address);
-         MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE);
+         MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, Dirty, FALSE, NULL);
      }
   }
 }
@@ -4208,9 +4060,7 @@
   PMEMORY_AREA MemoryArea;
   PMMSUPPORT AddressSpace;
   PROS_SECTION_OBJECT Section;
-   PMM_PAGEOP PageOp;
-   ULONG_PTR Offset;
-    PVOID ImageBaseAddress = 0;
+   PVOID ImageBaseAddress = 0;

   DPRINT("Opening memory area Process %x BaseAddress %x\n",
          Process, BaseAddress);
@@ -4232,40 +4082,6 @@
   }

   MemoryArea->DeleteInProgress = TRUE;
-
-   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 + MemoryArea->Data.SectionData.ViewOffset.QuadPart);
-         if (PageOp)
-         {
-            MmUnlockAddressSpace(AddressSpace);
-            Status = MmspWaitForPageOpCompletionEvent(PageOp);
-            if (Status != STATUS_SUCCESS)
-            {
-               DPRINT1("Failed to wait for page op, status = %x\n", Status);
-               KeBugCheck(MEMORY_MANAGEMENT);
-            }
-            MmLockAddressSpace(AddressSpace);
-            MmspCompleteAndReleasePageOp(PageOp);
-            MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace,
-                                                     BaseAddress);
-            if (MemoryArea == NULL ||
-                MemoryArea->Type != MEMORY_AREA_SECTION_VIEW)
-            {
-               MmUnlockAddressSpace(AddressSpace);
-               return STATUS_NOT_MAPPED_VIEW;
-            }
-            break;
-         }
-      }
-   }

   Section = MemoryArea->Data.SectionData.Section;