Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenrmap.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
1.7.6.1
|