ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rmap.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top directory
00003  * PROJECT:         ReactOS kernel
00004  * FILE:            ntoskrnl/mm/rmap.c
00005  * PURPOSE:         Kernel memory managment functions
00006  *
00007  * PROGRAMMERS:     David Welch (welch@cwcom.net)
00008  */
00009 
00010 /* INCLUDES *****************************************************************/
00011 
00012 #include <ntoskrnl.h>
00013 #include "../cache/section/newmm.h"
00014 #define NDEBUG
00015 #include <debug.h>
00016 
00017 #if defined (ALLOC_PRAGMA)
00018 #pragma alloc_text(INIT, MmInitializeRmapList)
00019 #endif
00020 
00021 /* TYPES ********************************************************************/
00022 
00023 /* GLOBALS ******************************************************************/
00024 
00025 static NPAGED_LOOKASIDE_LIST RmapLookasideList;
00026 FAST_MUTEX RmapListLock;
00027 
00028 /* FUNCTIONS ****************************************************************/
00029 
00030 VOID
00031 INIT_FUNCTION
00032 NTAPI
00033 MmInitializeRmapList(VOID)
00034 {
00035    ExInitializeFastMutex(&RmapListLock);
00036    ExInitializeNPagedLookasideList (&RmapLookasideList,
00037                                     NULL,
00038                                     NULL,
00039                                     0,
00040                                     sizeof(MM_RMAP_ENTRY),
00041                                     TAG_RMAP,
00042                                     50);
00043 }
00044 
00045 NTSTATUS
00046 NTAPI
00047 MmPageOutPhysicalAddress(PFN_NUMBER Page)
00048 {
00049    PMM_RMAP_ENTRY entry;
00050    PMEMORY_AREA MemoryArea;
00051    PMMSUPPORT AddressSpace;
00052    ULONG Type;
00053    PVOID Address;
00054    PEPROCESS Process;
00055    ULONGLONG Offset;
00056    NTSTATUS Status = STATUS_SUCCESS;
00057 
00058    ExAcquireFastMutex(&RmapListLock);
00059    entry = MmGetRmapListHeadPage(Page);
00060 
00061 #ifdef NEWCC
00062    // Special case for NEWCC: we can have a page that's only in a segment
00063    // page table
00064    if (entry && RMAP_IS_SEGMENT(entry->Address) && entry->Next == NULL)
00065    {
00066        /* NEWCC does locking itself */
00067        ExReleaseFastMutex(&RmapListLock);
00068        return MmpPageOutPhysicalAddress(Page);
00069    }
00070 #endif
00071 
00072    while (entry && RMAP_IS_SEGMENT(entry->Address))
00073        entry = entry->Next;
00074 
00075    if (entry == NULL)
00076    {
00077       ExReleaseFastMutex(&RmapListLock);
00078       return(STATUS_UNSUCCESSFUL);
00079    }
00080 
00081    Process = entry->Process;
00082 
00083    Address = entry->Address;
00084 
00085    if ((((ULONG_PTR)Address) & 0xFFF) != 0)
00086    {
00087       KeBugCheck(MEMORY_MANAGEMENT);
00088    }
00089 
00090    if (Address < MmSystemRangeStart)
00091    {
00092        if (!ExAcquireRundownProtection(&Process->RundownProtect))
00093        {
00094           ExReleaseFastMutex(&RmapListLock);
00095           return STATUS_PROCESS_IS_TERMINATING;
00096        }
00097 
00098       Status = ObReferenceObjectByPointer(Process, PROCESS_ALL_ACCESS, NULL, KernelMode);
00099       ExReleaseFastMutex(&RmapListLock);
00100       if (!NT_SUCCESS(Status))
00101       {
00102          ExReleaseRundownProtection(&Process->RundownProtect);
00103          return Status;
00104       }
00105       AddressSpace = &Process->Vm;
00106    }
00107    else
00108    {
00109       ExReleaseFastMutex(&RmapListLock);
00110       AddressSpace = MmGetKernelAddressSpace();
00111    }
00112 
00113    MmLockAddressSpace(AddressSpace);
00114    MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
00115    if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
00116    {
00117       MmUnlockAddressSpace(AddressSpace);
00118       if (Address < MmSystemRangeStart)
00119       {
00120          ExReleaseRundownProtection(&Process->RundownProtect);
00121          ObDereferenceObject(Process);
00122       }
00123       return(STATUS_UNSUCCESSFUL);
00124    }
00125    Type = MemoryArea->Type;
00126    if (Type == MEMORY_AREA_SECTION_VIEW)
00127    {
00128       ULONG_PTR Entry;
00129       Offset = MemoryArea->Data.SectionData.ViewOffset.QuadPart +
00130                ((ULONG_PTR)Address - (ULONG_PTR)MemoryArea->StartingAddress);
00131 
00132       MmLockSectionSegment(MemoryArea->Data.SectionData.Segment);
00133 
00134       /*
00135        * Get or create a pageop
00136        */
00137       Entry = MmGetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment,
00138                                            (PLARGE_INTEGER)&Offset);
00139       if (Entry && IS_SWAP_FROM_SSE(Entry) && SWAPENTRY_FROM_SSE(Entry) == MM_WAIT_ENTRY)
00140       {
00141          MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
00142          MmUnlockAddressSpace(AddressSpace);
00143          if (Address < MmSystemRangeStart)
00144          {
00145             ExReleaseRundownProtection(&Process->RundownProtect);
00146             ObDereferenceObject(Process);
00147          }
00148          return(STATUS_UNSUCCESSFUL);
00149       }
00150 
00151       MmSetPageEntrySectionSegment(MemoryArea->Data.SectionData.Segment, (PLARGE_INTEGER)&Offset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
00152 
00153       /*
00154        * Release locks now we have a page op.
00155        */
00156       MmUnlockSectionSegment(MemoryArea->Data.SectionData.Segment);
00157       MmUnlockAddressSpace(AddressSpace);
00158 
00159       /*
00160        * Do the actual page out work.
00161        */
00162       Status = MmPageOutSectionView(AddressSpace, MemoryArea, Address, Entry);
00163    }
00164    else if (Type == MEMORY_AREA_CACHE)
00165    {
00166        /* NEWCC does locking itself */
00167        MmUnlockAddressSpace(AddressSpace);
00168        Status = MmpPageOutPhysicalAddress(Page);
00169    }
00170    else
00171    {
00172       KeBugCheck(MEMORY_MANAGEMENT);
00173    }
00174 
00175    if (Address < MmSystemRangeStart)
00176    {
00177       ExReleaseRundownProtection(&Process->RundownProtect);
00178       ObDereferenceObject(Process);
00179    }
00180    return(Status);
00181 }
00182 
00183 VOID
00184 NTAPI
00185 MmSetCleanAllRmaps(PFN_NUMBER Page)
00186 {
00187    PMM_RMAP_ENTRY current_entry;
00188 
00189    ExAcquireFastMutex(&RmapListLock);
00190    current_entry = MmGetRmapListHeadPage(Page);
00191    if (current_entry == NULL)
00192    {
00193       DPRINT1("MmIsDirtyRmap: No rmaps.\n");
00194       KeBugCheck(MEMORY_MANAGEMENT);
00195    }
00196    while (current_entry != NULL)
00197    {
00198       if (!RMAP_IS_SEGMENT(current_entry->Address))
00199          MmSetCleanPage(current_entry->Process, current_entry->Address);
00200       current_entry = current_entry->Next;
00201    }
00202    ExReleaseFastMutex(&RmapListLock);
00203 }
00204 
00205 VOID
00206 NTAPI
00207 MmSetDirtyAllRmaps(PFN_NUMBER Page)
00208 {
00209    PMM_RMAP_ENTRY current_entry;
00210 
00211    ExAcquireFastMutex(&RmapListLock);
00212    current_entry = MmGetRmapListHeadPage(Page);
00213    if (current_entry == NULL)
00214    {
00215       DPRINT1("MmIsDirtyRmap: No rmaps.\n");
00216       KeBugCheck(MEMORY_MANAGEMENT);
00217    }
00218    while (current_entry != NULL)
00219    {
00220       if (!RMAP_IS_SEGMENT(current_entry->Address))
00221          MmSetDirtyPage(current_entry->Process, current_entry->Address);
00222       current_entry = current_entry->Next;
00223    }
00224    ExReleaseFastMutex(&RmapListLock);
00225 }
00226 
00227 BOOLEAN
00228 NTAPI
00229 MmIsDirtyPageRmap(PFN_NUMBER Page)
00230 {
00231    PMM_RMAP_ENTRY current_entry;
00232 
00233    ExAcquireFastMutex(&RmapListLock);
00234    current_entry = MmGetRmapListHeadPage(Page);
00235    if (current_entry == NULL)
00236    {
00237       ExReleaseFastMutex(&RmapListLock);
00238       return(FALSE);
00239    }
00240    while (current_entry != NULL)
00241    {
00242       if (
00243           !RMAP_IS_SEGMENT(current_entry->Address) &&
00244           MmIsDirtyPage(current_entry->Process, current_entry->Address))
00245       {
00246          ExReleaseFastMutex(&RmapListLock);
00247          return(TRUE);
00248       }
00249       current_entry = current_entry->Next;
00250    }
00251    ExReleaseFastMutex(&RmapListLock);
00252    return(FALSE);
00253 }
00254 
00255 VOID
00256 NTAPI
00257 MmInsertRmap(PFN_NUMBER Page, PEPROCESS Process,
00258              PVOID Address)
00259 {
00260    PMM_RMAP_ENTRY current_entry;
00261    PMM_RMAP_ENTRY new_entry;
00262    ULONG PrevSize;
00263    if (!RMAP_IS_SEGMENT(Address))
00264       Address = (PVOID)PAGE_ROUND_DOWN(Address);
00265 
00266    new_entry = ExAllocateFromNPagedLookasideList(&RmapLookasideList);
00267    if (new_entry == NULL)
00268    {
00269       KeBugCheck(MEMORY_MANAGEMENT);
00270    }
00271    new_entry->Address = Address;
00272    new_entry->Process = (PEPROCESS)Process;
00273 #if DBG
00274 #ifdef __GNUC__
00275    new_entry->Caller = __builtin_return_address(0);
00276 #else
00277    new_entry->Caller = _ReturnAddress();
00278 #endif
00279 #endif
00280 
00281    if (
00282        !RMAP_IS_SEGMENT(Address) &&
00283        MmGetPfnForProcess(Process, Address) != Page)
00284    {
00285       DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
00286               "address 0x%.8X\n", Process ? Process->UniqueProcessId : 0,
00287               Address,
00288               MmGetPfnForProcess(Process, Address) << PAGE_SHIFT,
00289               Page << PAGE_SHIFT);
00290       KeBugCheck(MEMORY_MANAGEMENT);
00291    }
00292 
00293    ExAcquireFastMutex(&RmapListLock);
00294    current_entry = MmGetRmapListHeadPage(Page);
00295    new_entry->Next = current_entry;
00296 #if DBG
00297    while (current_entry)
00298    {
00299       if (current_entry->Address == new_entry->Address && current_entry->Process == new_entry->Process)
00300       {
00301           DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n    current caller ",
00302                    current_entry->Address);
00303           DbgPrint("%p", new_entry->Caller);
00304           DbgPrint("\n    previous caller ");
00305           DbgPrint("%p", current_entry->Caller);
00306           DbgPrint("\n");
00307           KeBugCheck(MEMORY_MANAGEMENT);
00308       }
00309       current_entry = current_entry->Next;
00310    }
00311 #endif
00312    MmSetRmapListHeadPage(Page, new_entry);
00313    ExReleaseFastMutex(&RmapListLock);
00314    if (!RMAP_IS_SEGMENT(Address))
00315    {
00316       if (Process == NULL)
00317       {
00318          Process = PsInitialSystemProcess;
00319       }
00320       if (Process)
00321       {
00322          PrevSize = InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, PAGE_SIZE);
00323          if (PrevSize >= Process->Vm.PeakWorkingSetSize)
00324          {
00325             Process->Vm.PeakWorkingSetSize = PrevSize + PAGE_SIZE;
00326          }
00327       }
00328    }
00329 }
00330 
00331 VOID
00332 NTAPI
00333 MmDeleteAllRmaps(PFN_NUMBER Page, PVOID Context,
00334                  VOID (*DeleteMapping)(PVOID Context, PEPROCESS Process,
00335                                        PVOID Address))
00336 {
00337    PMM_RMAP_ENTRY current_entry;
00338    PMM_RMAP_ENTRY previous_entry;
00339    PEPROCESS Process;
00340 
00341    ExAcquireFastMutex(&RmapListLock);
00342    current_entry = MmGetRmapListHeadPage(Page);
00343    if (current_entry == NULL)
00344    {
00345       DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
00346       KeBugCheck(MEMORY_MANAGEMENT);
00347    }
00348    MmSetRmapListHeadPage(Page, NULL);
00349    ExReleaseFastMutex(&RmapListLock);
00350 
00351    while (current_entry != NULL)
00352    {
00353       previous_entry = current_entry;
00354       current_entry = current_entry->Next;
00355       if (!RMAP_IS_SEGMENT(previous_entry->Address))
00356       {
00357          if (DeleteMapping)
00358          {
00359             DeleteMapping(Context, previous_entry->Process,
00360                           previous_entry->Address);
00361          }
00362          Process = previous_entry->Process;
00363          ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
00364          if (Process == NULL)
00365          {
00366             Process = PsInitialSystemProcess;
00367          }
00368          if (Process)
00369          {
00370             (void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
00371          }
00372       }
00373       else
00374       {
00375          ExFreeToNPagedLookasideList(&RmapLookasideList, previous_entry);
00376       }
00377    }
00378 }
00379 
00380 VOID
00381 NTAPI
00382 MmDeleteRmap(PFN_NUMBER Page, PEPROCESS Process,
00383              PVOID Address)
00384 {
00385    PMM_RMAP_ENTRY current_entry, previous_entry;
00386 
00387    ExAcquireFastMutex(&RmapListLock);
00388    previous_entry = NULL;
00389    current_entry = MmGetRmapListHeadPage(Page);
00390 
00391    while (current_entry != NULL)
00392    {
00393       if (current_entry->Process == (PEPROCESS)Process &&
00394             current_entry->Address == Address)
00395       {
00396          if (previous_entry == NULL)
00397          {
00398             MmSetRmapListHeadPage(Page, current_entry->Next);
00399          }
00400          else
00401          {
00402             previous_entry->Next = current_entry->Next;
00403          }
00404          ExReleaseFastMutex(&RmapListLock);
00405          ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
00406          if (!RMAP_IS_SEGMENT(Address))
00407          {
00408             if (Process == NULL)
00409             {
00410                Process = PsInitialSystemProcess;
00411             }
00412             if (Process)
00413             {
00414                (void)InterlockedExchangeAddUL(&Process->Vm.WorkingSetSize, -PAGE_SIZE);
00415             }
00416          }
00417          return;
00418       }
00419       previous_entry = current_entry;
00420       current_entry = current_entry->Next;
00421    }
00422    KeBugCheck(MEMORY_MANAGEMENT);
00423 }
00424 
00425 /*
00426 
00427 Return the process pointer given when a previous call to MmInsertRmap was
00428 called with a process and address pointer that conform to the segment rmap
00429 schema.  In short, this requires the address part to be 0xffffff00 + n
00430 where n is between 0 and 255.  When such an rmap exists, it specifies a
00431 segment rmap in which the process part is a pointer to a slice of a section
00432 page table, and the low 8 bits of the address represent a page index in the
00433 page table slice.  Together, this information is used by
00434 MmGetSectionAssociation to determine which page entry points to this page in
00435 the segment page table.
00436 
00437 */
00438 
00439 PVOID
00440 NTAPI
00441 MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset)
00442 {
00443    PCACHE_SECTION_PAGE_TABLE Result = NULL;
00444    PMM_RMAP_ENTRY current_entry, previous_entry;
00445 
00446    ExAcquireFastMutex(&RmapListLock);
00447    previous_entry = NULL;
00448    current_entry = MmGetRmapListHeadPage(Page);
00449    while (current_entry != NULL)
00450    {
00451       if (RMAP_IS_SEGMENT(current_entry->Address))
00452       {
00453          Result = (PCACHE_SECTION_PAGE_TABLE)current_entry->Process;
00454          *RawOffset = (ULONG_PTR)current_entry->Address & ~RMAP_SEGMENT_MASK;
00455          InterlockedIncrementUL(&Result->Segment->ReferenceCount);
00456          ExReleaseFastMutex(&RmapListLock);
00457          return Result;
00458       }
00459       previous_entry = current_entry;
00460       current_entry = current_entry->Next;
00461    }
00462    ExReleaseFastMutex(&RmapListLock);
00463    return NULL;
00464 }
00465 
00466 /*
00467 
00468 Remove the section rmap associated with the indicated page, if it exists.
00469 
00470 */
00471 
00472 VOID
00473 NTAPI
00474 MmDeleteSectionAssociation(PFN_NUMBER Page)
00475 {
00476    PMM_RMAP_ENTRY current_entry, previous_entry;
00477 
00478    ExAcquireFastMutex(&RmapListLock);
00479    previous_entry = NULL;
00480    current_entry = MmGetRmapListHeadPage(Page);
00481    while (current_entry != NULL)
00482    {
00483       if (RMAP_IS_SEGMENT(current_entry->Address))
00484       {
00485          if (previous_entry == NULL)
00486          {
00487             MmSetRmapListHeadPage(Page, current_entry->Next);
00488          }
00489          else
00490          {
00491             previous_entry->Next = current_entry->Next;
00492          }
00493          ExReleaseFastMutex(&RmapListLock);
00494          ExFreeToNPagedLookasideList(&RmapLookasideList, current_entry);
00495          return;
00496       }
00497       previous_entry = current_entry;
00498       current_entry = current_entry->Next;
00499    }
00500    ExReleaseFastMutex(&RmapListLock);
00501 }

Generated on Sun May 27 2012 04:37:39 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.