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;
 


Reply via email to