Release the rmap list lock after cleaning the head entry in MmDeleteAllRmaps. This...
[reactos.git] / reactos / ntoskrnl / mm / rmap.c
index 33c1968..402706b 100644 (file)
@@ -1,30 +1,11 @@
-/*
- *  ReactOS kernel
- *  Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
 /* $Id$
  *
- * COPYRIGHT:   See COPYING in the top directory
- * PROJECT:     ReactOS kernel 
- * FILE:        ntoskrnl/mm/rmap.c
- * PURPOSE:     kernel memory managment functions
- * PROGRAMMER:  David Welch (welch@cwcom.net)
- * UPDATE HISTORY:
- *              Created 27/12/01
+ * COPYRIGHT:       See COPYING in the top directory
+ * PROJECT:         ReactOS kernel
+ * FILE:            ntoskrnl/mm/rmap.c
+ * PURPOSE:         Kernel memory managment functions
+ *
+ * PROGRAMMERS:     David Welch (welch@cwcom.net)
  */
 
 /* INCLUDES *****************************************************************/
 #define NDEBUG
 #include <internal/debug.h>
 
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, MmInitializeRmapList)
+#endif
+
 /* TYPES ********************************************************************/
 
 typedef struct _MM_RMAP_ENTRY
@@ -40,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;
@@ -52,7 +38,9 @@ static NPAGED_LOOKASIDE_LIST RmapLookasideList;
 
 /* FUNCTIONS ****************************************************************/
 
-VOID INIT_FUNCTION
+VOID
+INIT_FUNCTION
+NTAPI
 MmInitializeRmapList(VOID)
 {
    ExInitializeFastMutex(&RmapListLock);
@@ -66,6 +54,7 @@ MmInitializeRmapList(VOID)
 }
 
 NTSTATUS
+NTAPI
 MmWritePagePhysicalAddress(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY entry;
@@ -95,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);
@@ -114,14 +103,14 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
    /*
     * Lock the address space; then check that the address we are using
     * still corresponds to a valid memory area (the page might have been
-    * freed or paged out after we read the rmap entry.) 
+    * freed or paged out after we read the rmap entry.)
     */
    MmLockAddressSpace(AddressSpace);
    MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
    if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
    {
       MmUnlockAddressSpace(AddressSpace);
-      if (Address < (PVOID)KERNEL_BASE)
+      if (Address < MmSystemRangeStart)
       {
          ObDereferenceObject(Process);
       }
@@ -131,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
        */
@@ -143,7 +132,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
       if (PageOp == NULL)
       {
          MmUnlockAddressSpace(AddressSpace);
-         if (Address < (PVOID)KERNEL_BASE)
+         if (Address < MmSystemRangeStart)
          {
             ObDereferenceObject(Process);
          }
@@ -161,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);
          }
@@ -191,7 +180,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
    {
       KEBUGCHECK(0);
    }
-   if (Address < (PVOID)KERNEL_BASE)
+   if (Address < MmSystemRangeStart)
    {
       ObDereferenceObject(Process);
    }
@@ -199,6 +188,7 @@ MmWritePagePhysicalAddress(PFN_TYPE Page)
 }
 
 NTSTATUS
+NTAPI
 MmPageOutPhysicalAddress(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY entry;
@@ -225,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);
@@ -246,7 +236,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
    if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
    {
       MmUnlockAddressSpace(AddressSpace);
-      if (Address < (PVOID)KERNEL_BASE)
+      if (Address < MmSystemRangeStart)
       {
          ObDereferenceObject(Process);
       }
@@ -255,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
@@ -266,7 +257,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
       if (PageOp == NULL)
       {
          MmUnlockAddressSpace(AddressSpace);
-         if (Address < (PVOID)KERNEL_BASE)
+         if (Address < MmSystemRangeStart)
          {
             ObDereferenceObject(Process);
          }
@@ -284,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);
          }
@@ -313,7 +304,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
    {
       KEBUGCHECK(0);
    }
-   if (Address < (PVOID)KERNEL_BASE)
+   if (Address < MmSystemRangeStart)
    {
       ObDereferenceObject(Process);
    }
@@ -321,6 +312,7 @@ MmPageOutPhysicalAddress(PFN_TYPE Page)
 }
 
 VOID
+NTAPI
 MmSetCleanAllRmaps(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY current_entry;
@@ -341,6 +333,7 @@ MmSetCleanAllRmaps(PFN_TYPE Page)
 }
 
 VOID
+NTAPI
 MmSetDirtyAllRmaps(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY current_entry;
@@ -361,6 +354,7 @@ MmSetDirtyAllRmaps(PFN_TYPE Page)
 }
 
 BOOL
+NTAPI
 MmIsDirtyPageRmap(PFN_TYPE Page)
 {
    PMM_RMAP_ENTRY current_entry;
@@ -386,6 +380,7 @@ MmIsDirtyPageRmap(PFN_TYPE Page)
 }
 
 VOID
+NTAPI
 MmInsertRmap(PFN_TYPE Page, PEPROCESS Process,
              PVOID Address)
 {
@@ -402,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)
    {
@@ -415,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)
@@ -432,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))
@@ -448,6 +463,7 @@ MmDeleteAllRmaps(PFN_TYPE Page, PVOID Context,
       KEBUGCHECK(0);
    }
    MmSetRmapListHeadPage(Page, NULL);
+   ExReleaseFastMutex(&RmapListLock);
    while (current_entry != NULL)
    {
       previous_entry = current_entry;
@@ -468,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)
 {