Author: arty
Date: Thu May  3 21:05:06 2012
New Revision: 56488

URL: http://svn.reactos.org/svn/reactos?rev=56488&view=rev
Log:
[NTOSKRNL]
Account for wait entries delaying a view attribute change and interacting
with the machinery in CoW copying code, specifically making CoW insert and
revoke a wait while copying the page, and make the CoW copy function take
both pages as arguments rather than relying on the address space.

Also alter the MM_WAIT_ENTRY value a bit to take into account an assert
that it must have bit 0x800 set.

Modified:
    trunk/reactos/ntoskrnl/cache/section/newmm.h
    trunk/reactos/ntoskrnl/include/internal/mm.h
    trunk/reactos/ntoskrnl/mm/i386/page.c
    trunk/reactos/ntoskrnl/mm/section.c

Modified: trunk/reactos/ntoskrnl/cache/section/newmm.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/cache/section/newmm.h?rev=56488&r1=56487&r2=56488&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/cache/section/newmm.h [iso-8859-1] Thu May  3 
21:05:06 2012
@@ -4,7 +4,7 @@
 
 /* TYPES *********************************************************************/
 
-#define MM_WAIT_ENTRY            0x7ffff800
+#define MM_WAIT_ENTRY            0x7ffffc00
 #define PFN_FROM_SSE(E)          ((PFN_NUMBER)((E) >> PAGE_SHIFT))
 #define IS_SWAP_FROM_SSE(E)      ((E) & 0x00000001)
 #define MM_IS_WAIT_PTE(E)        \

Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/mm.h?rev=56488&r1=56487&r2=56488&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h [iso-8859-1] Thu May  3 
21:05:06 2012
@@ -955,8 +955,8 @@
 NTSTATUS
 NTAPI
 MiCopyFromUserPage(
-    PFN_NUMBER Page,
-    PVOID SourceAddress
+    PFN_NUMBER NewPage,
+    PFN_NUMBER OldPage
 );
 
 NTSTATUS

Modified: trunk/reactos/ntoskrnl/mm/i386/page.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/i386/page.c?rev=56488&r1=56487&r2=56488&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/i386/page.c [iso-8859-1] Thu May  3 21:05:06 2012
@@ -558,6 +558,7 @@
 
     if ((Pte & PA_PRESENT) || !(Pte & 0x800))
     {
+        DPRINT1("Pte %x (want not 1 and 0x800)\n", Pte);
         KeBugCheck(MEMORY_MANAGEMENT);
     }
 

Modified: trunk/reactos/ntoskrnl/mm/section.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/section.c?rev=56488&r1=56487&r2=56488&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/section.c [iso-8859-1] Thu May  3 21:05:06 2012
@@ -959,22 +959,24 @@
 
 NTSTATUS
 NTAPI
-MiCopyFromUserPage(PFN_NUMBER DestPage, PVOID SourceAddress)
+MiCopyFromUserPage(PFN_NUMBER DestPage, PFN_NUMBER SrcPage)
 {
     PEPROCESS Process;
-    KIRQL Irql;
-    PVOID TempAddress;
-
-    ASSERT((ULONG_PTR)SourceAddress % PAGE_SIZE == 0);
+    KIRQL Irql, Irql2;
+    PVOID DestAddress, SrcAddress;
+
     Process = PsGetCurrentProcess();
-    TempAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
-    if (TempAddress == NULL)
+    DestAddress = MiMapPageInHyperSpace(Process, DestPage, &Irql);
+    SrcAddress = MiMapPageInHyperSpace(Process, SrcPage, &Irql2);
+    if (DestAddress == NULL || SrcAddress == NULL)
     {
         return(STATUS_NO_MEMORY);
     }
-    ASSERT((ULONG_PTR)TempAddress % PAGE_SIZE == 0);
-    RtlCopyMemory(TempAddress, SourceAddress, PAGE_SIZE);
-    MiUnmapPageInHyperSpace(Process, TempAddress, Irql);
+    ASSERT((ULONG_PTR)DestAddress % PAGE_SIZE == 0);
+    ASSERT((ULONG_PTR)SrcAddress % PAGE_SIZE == 0);
+    RtlCopyMemory(DestAddress, SrcAddress, PAGE_SIZE);
+    MiUnmapPageInHyperSpace(Process, SrcAddress, Irql2);
+    MiUnmapPageInHyperSpace(Process, DestAddress, Irql);
     return(STATUS_SUCCESS);
 }
 
@@ -1620,6 +1622,7 @@
    PMM_REGION Region;
    ULONG_PTR Entry;
    PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
+   SWAPENTRY SwapEntry;
 
    DPRINT("MmAccessFaultSectionView(%x, %x, %x, %x)\n", AddressSpace, 
MemoryArea, Address);
 
@@ -1699,6 +1702,10 @@
        return(STATUS_MM_RESTART_OPERATION);
    }
 
+   MmDeleteRmap(OldPage, Process, PAddress);
+   MmDeleteVirtualMapping(Process, PAddress, FALSE, NULL, NULL);
+   MmCreatePageFileMapping(Process, PAddress, MM_WAIT_ENTRY);
+
    /*
     * Release locks now we have the pageop
     */
@@ -1720,17 +1727,14 @@
    /*
     * Copy the old page
     */
-   MiCopyFromUserPage(NewPage, PAddress);
+   MiCopyFromUserPage(NewPage, OldPage);
 
    MmLockAddressSpace(AddressSpace);
-   /*
-    * Delete the old entry.
-    */
-   MmDeleteVirtualMapping(Process, Address, FALSE, NULL, NULL);
 
    /*
     * Set the PTE to point to the new page
     */
+   MmDeletePageFileMapping(Process, PAddress, &SwapEntry);
    Status = MmCreateVirtualMapping(Process,
                                    PAddress,
                                    Region->Protect,
@@ -1751,7 +1755,7 @@
    /*
     * Unshare the old page.
     */
-   MmDeleteRmap(OldPage, Process, PAddress);
+   DPRINT("Swapping page (Old %x New %x)\n", OldPage, NewPage);
    MmInsertRmap(NewPage, Process, PAddress);
    MmLockSectionSegment(Segment);
    MmUnsharePageEntrySectionSegment(Section, Segment, &Offset, FALSE, FALSE, 
NULL);
@@ -2388,8 +2392,17 @@
    {
       for (i = 0; i < PAGE_ROUND_UP(RegionSize) / PAGE_SIZE; i++)
       {
+         SWAPENTRY SwapEntry;
          PVOID Address = (char*)BaseAddress + (i * PAGE_SIZE);
          ULONG Protect = NewProtect;
+
+         /* Wait for a wait entry to disappear */
+         do {
+             MmGetPageFileMapping(Process, Address, &SwapEntry);
+             if (SwapEntry != MM_WAIT_ENTRY)
+                 break;
+             MiWaitForPageEvent(Process, Address);
+         } while (TRUE);
 
          /*
           * If we doing COW for this segment then check if the page is
@@ -2404,6 +2417,10 @@
             Offset.QuadPart = (ULONG_PTR)Address - 
(ULONG_PTR)MemoryArea->StartingAddress
                      + MemoryArea->Data.SectionData.ViewOffset.QuadPart;
             Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
+            /*
+             * An MM_WAIT_ENTRY is ok in this case...  It'll just count as 
+             * IS_SWAP_FROM_SSE and we'll do the right thing.
+             */
             Page = MmGetPfnForProcess(Process, Address);
 
             Protect = PAGE_READONLY;


Reply via email to