Release the rmap list lock after cleaning the head entry in MmDeleteAllRmaps. This...
[reactos.git] / reactos / ntoskrnl / mm / rmap.c
index d12dfaa..402706b 100644 (file)
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, MmInitializeRmapList)
+#endif
+
 /* TYPES ********************************************************************/
 
 typedef struct _MM_RMAP_ENTRY
@@ -21,11 +25,12 @@ typedef struct _MM_RMAP_ENTRY
    struct _MM_RMAP_ENTRY* Next;
    PEPROCESS Process;
    PVOID Address;
+#ifdef DBG
+   PVOID Caller;
+#endif
 }
 MM_RMAP_ENTRY, *PMM_RMAP_ENTRY;
 
-#define TAG_RMAP    TAG('R', 'M', 'A', 'P')
-
 /* GLOBALS ******************************************************************/
 
 static FAST_MUTEX RmapListLock;
@@ -33,7 +38,9 @@ static NPAGED_LOOKASIDE_LIST RmapLookasideList;
 
 /* FUNCTIONS ****************************************************************/
 
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
+NTAPI
 MmInitializeRmapList(VOID)
 {
    ExInitializeFastMutex(&RmapListLock);
@@ -47,6 +54,7 @@ MmInitializeRmapList(VOID)
 }
 
 NTSTATUS
+NTAPI
 MmWritePagePhysicalAddress(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY entry;
@@ -76,7 +84,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
    {
       KEBUGCHECK(0);
    }
-   if (Address < (PVOID)KERNEL_BASE)
+   if (Address < MmSystemRangeStart)
    {
       Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
       ExReleaseFastMutex(&RmapListLock);
@@ -102,7 +110,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
    if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
    {
       MmUnlockAddressSpace(AddressSpace);
-      if (Address < (PVOID)KERNEL_BASE)
+      if (Address < MmSystemRangeStart)
       {
          ObDereferenceObject(Process);
       }
@@ -112,8 +120,8 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
    Type = MemoryArea->Type;
    if (Type == MEMORY_AREA_SECTION_VIEW)
    {
-      Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
-
+      Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+               + MemoryArea->Data.SectionData.ViewOffset;
       /*
        * Get or create a pageop
        */
@@ -124,7 +132,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
       if (PageOp == NULL)
       {
          MmUnlockAddressSpace(AddressSpace);
-         if (Address < (PVOID)KERNEL_BASE)
+         if (Address < MmSystemRangeStart)
          {
             ObDereferenceObject(Process);
          }
@@ -142,15 +150,15 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
       Status = MmWritePageSectionView(AddressSpace, MemoryArea,
                                       Address, PageOp);
    }
-   else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
+   else if ((Type == MEMORY_AREA_VIRTUAL_MEMORY) || (Type == MEMORY_AREA_PEB_OR_TEB))
    {
-      PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : NULL,
+      PageOp = MmGetPageOp(MemoryArea, Address < MmSystemRangeStart ? Process->UniqueProcessId : NULL,
                            Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
 
       if (PageOp == NULL)
       {
          MmUnlockAddressSpace(AddressSpace);
-         if (Address < (PVOID)KERNEL_BASE)
+         if (Address < MmSystemRangeStart)
          {
             ObDereferenceObject(Process);
          }
@@ -172,7 +180,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
    {
       KEBUGCHECK(0);
    }
-   if (Address < (PVOID)KERNEL_BASE)
+   if (Address < MmSystemRangeStart)
    {
       ObDereferenceObject(Process);
    }
@@ -180,6 +188,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
 }
 
 NTSTATUS
+NTAPI
 MmPageOutPhysicalAddress(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY entry;
@@ -206,7 +215,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
       KEBUGCHECK(0);
    }
 
-   if (Address < (PVOID)KERNEL_BASE)
+   if (Address < MmSystemRangeStart)
    {
       Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
       ExReleaseFastMutex(&RmapListLock);
@@ -227,7 +236,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
    if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
    {
       MmUnlockAddressSpace(AddressSpace);
-      if (Address < (PVOID)KERNEL_BASE)
+      if (Address < MmSystemRangeStart)
       {
          ObDereferenceObject(Process);
       }
@@ -236,7 +245,8 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
    Type = MemoryArea->Type;
    if (Type == MEMORY_AREA_SECTION_VIEW)
    {
-      Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress;
+      Offset = (ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress 
+             + MemoryArea->Data.SectionData.ViewOffset;;
 
       /*
        * Get or create a pageop
@@ -247,7 +257,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
       if (PageOp == NULL)
       {
          MmUnlockAddressSpace(AddressSpace);
-         if (Address < (PVOID)KERNEL_BASE)
+         if (Address < MmSystemRangeStart)
          {
             ObDereferenceObject(Process);
          }
@@ -265,14 +275,14 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
       Status = MmPageOutSectionView(AddressSpace, MemoryArea,
                                     Address, PageOp);
    }
-   else if (Type == MEMORY_AREA_VIRTUAL_MEMORY)
+   else if ((Type == MEMORY_AREA_VIRTUAL_MEMORY) || (Type == MEMORY_AREA_PEB_OR_TEB))
    {
-      PageOp = MmGetPageOp(MemoryArea, Address < (PVOID)KERNEL_BASE ? Process->UniqueProcessId : NULL,
+      PageOp = MmGetPageOp(MemoryArea, Address < MmSystemRangeStart ? Process->UniqueProcessId : NULL,
                            Address, NULL, 0, MM_PAGEOP_PAGEOUT, TRUE);
       if (PageOp == NULL)
       {
          MmUnlockAddressSpace(AddressSpace);
-         if (Address < (PVOID)KERNEL_BASE)
+         if (Address < MmSystemRangeStart)
          {
             ObDereferenceObject(Process);
          }
@@ -294,7 +304,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
    {
       KEBUGCHECK(0);
    }
-   if (Address < (PVOID)KERNEL_BASE)
+   if (Address < MmSystemRangeStart)
    {
       ObDereferenceObject(Process);
    }
@@ -302,6 +312,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
 }
 
 VOID
+NTAPI
 MmSetCleanAllRmaps(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY current_entry;
@@ -322,6 +333,7 @@ MmSetCleanAllRmaps(PFN_TYPE Page)
 }
 
 VOID
+NTAPI
 MmSetDirtyAllRmaps(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY current_entry;
@@ -342,6 +354,7 @@ MmSetDirtyAllRmaps(PFN_TYPE Page)
 }
 
 BOOL
+NTAPI
 MmIsDirtyPageRmap(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY current_entry;
@@ -367,6 +380,7 @@ MmIsDirtyPageRmap(PFN_TYPE Page)
 }
 
 VOID
+NTAPI
 MmInsertRmap(PFN_TYPE Page, PEPROCESS Process,
              PVOID Address)
 {
@@ -383,6 +397,9 @@ MmInsertRmap(PFN_TYPE Page, PEPROCESS Process,
    }
    new_entry->Address = Address;
    new_entry->Process = Process;
+#ifdef DBG
+   new_entry->Caller = __builtin_return_address(0);
+#endif   
 
    if (MmGetPfnForProcess(Process, Address) != Page)
    {
@@ -396,6 +413,22 @@ MmInsertRmap(PFN_TYPE Page, PEPROCESS Process,
    ExAcquireFastMutex(&RmapListLock);
    current_entry = MmGetRmapListHeadPage(Page);
    new_entry->Next = current_entry;
+#ifdef DBG
+   while (current_entry)
+   {
+      if (current_entry->Address == new_entry->Address && current_entry->Process == new_entry->Process)
+      {
+          DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n    current caller ", 
+                   current_entry->Address);
+          KeRosPrintAddress(new_entry->Caller);
+          DbgPrint("\n    previous caller ");
+          KeRosPrintAddress(current_entry->Caller);
+          DbgPrint("\n");
+          KeBugCheck(0);
+      }
+      current_entry = current_entry->Next;
+   }
+#endif
    MmSetRmapListHeadPage(Page, new_entry);
    ExReleaseFastMutex(&RmapListLock);
    if (Process == NULL)
@@ -413,6 +446,7 @@ MmInsertRmap(PFN_TYPE Page, PEPROCESS Process,
 }
 
 VOID
+NTAPI
 MmDeleteAllRmaps(PFN_TYPE Page, PVOID Context,
                  VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
                                        PVOID Address))
@@ -429,6 +463,7 @@ MmDeleteAllRmaps(PFN_TYPE Page, PVOID Context,
       KEBUGCHECK(0);
    }
    MmSetRmapListHeadPage(Page, NULL);
+   ExReleaseFastMutex(&RmapListLock);
    while (current_entry != NULL)
    {
       previous_entry = current_entry;
@@ -449,10 +484,10 @@ MmDeleteAllRmaps(PFN_TYPE Page, PVOID Context,
          InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
       }
    }
-   ExReleaseFastMutex(&RmapListLock);
 }
 
 VOID
+NTAPI
 MmDeleteRmap(PFN_TYPE Page, PEPROCESS Process,
              PVOID Address)
 {