2 * COPYRIGHT: See COPYING in the top directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/rmap.c
5 * PURPOSE: Kernel memory managment functions
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
10 /* INCLUDES *****************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, MmInitializeRmapList)
20 /* TYPES ********************************************************************/
22 /* GLOBALS ******************************************************************/
24 static FAST_MUTEX RmapListLock
;
25 static NPAGED_LOOKASIDE_LIST RmapLookasideList
;
27 /* FUNCTIONS ****************************************************************/
32 MmInitializeRmapList(VOID
)
34 ExInitializeFastMutex(&RmapListLock
);
35 ExInitializeNPagedLookasideList (&RmapLookasideList
,
39 sizeof(MM_RMAP_ENTRY
),
46 MmPageOutPhysicalAddress(PFN_NUMBER Page
)
49 PMEMORY_AREA MemoryArea
;
50 PMMSUPPORT AddressSpace
;
56 NTSTATUS Status
= STATUS_SUCCESS
;
58 ExAcquireFastMutex(&RmapListLock
);
59 entry
= MmGetRmapListHeadPage(Page
);
62 ExReleaseFastMutex(&RmapListLock
);
63 return(STATUS_UNSUCCESSFUL
);
65 Process
= entry
->Process
;
67 Address
= entry
->Address
;
68 if ((((ULONG_PTR
)Address
) & 0xFFF) != 0)
70 KeBugCheck(MEMORY_MANAGEMENT
);
73 if (Address
< MmSystemRangeStart
)
75 if (!ExAcquireRundownProtection(&Process
->RundownProtect
))
77 ExReleaseFastMutex(&RmapListLock
);
78 return STATUS_PROCESS_IS_TERMINATING
;
81 Status
= ObReferenceObjectByPointer(Process
, PROCESS_ALL_ACCESS
, NULL
, KernelMode
);
82 ExReleaseFastMutex(&RmapListLock
);
83 if (!NT_SUCCESS(Status
))
85 ExReleaseRundownProtection(&Process
->RundownProtect
);
88 AddressSpace
= &Process
->Vm
;
92 ExReleaseFastMutex(&RmapListLock
);
93 AddressSpace
= MmGetKernelAddressSpace();
96 MmLockAddressSpace(AddressSpace
);
97 MemoryArea
= MmLocateMemoryAreaByAddress(AddressSpace
, Address
);
98 if (MemoryArea
== NULL
|| MemoryArea
->DeleteInProgress
)
100 MmUnlockAddressSpace(AddressSpace
);
101 if (Address
< MmSystemRangeStart
)
103 ExReleaseRundownProtection(&Process
->RundownProtect
);
104 ObDereferenceObject(Process
);
106 return(STATUS_UNSUCCESSFUL
);
108 Type
= MemoryArea
->Type
;
109 if (Type
== MEMORY_AREA_SECTION_VIEW
)
111 Offset
= (ULONG_PTR
)Address
- (ULONG_PTR
)MemoryArea
->StartingAddress
112 + MemoryArea
->Data
.SectionData
.ViewOffset
;
115 * Get or create a pageop
117 PageOp
= MmGetPageOp(MemoryArea
, NULL
, 0,
118 MemoryArea
->Data
.SectionData
.Segment
,
119 Offset
, MM_PAGEOP_PAGEOUT
, TRUE
);
122 MmUnlockAddressSpace(AddressSpace
);
123 if (Address
< MmSystemRangeStart
)
125 ExReleaseRundownProtection(&Process
->RundownProtect
);
126 ObDereferenceObject(Process
);
128 return(STATUS_UNSUCCESSFUL
);
132 * Release locks now we have a page op.
134 MmUnlockAddressSpace(AddressSpace
);
137 * Do the actual page out work.
139 Status
= MmPageOutSectionView(AddressSpace
, MemoryArea
,
142 else if (Type
== MEMORY_AREA_VIRTUAL_MEMORY
)
144 PageOp
= MmGetPageOp(MemoryArea
, Address
< MmSystemRangeStart
? Process
->UniqueProcessId
: NULL
,
145 Address
, NULL
, 0, MM_PAGEOP_PAGEOUT
, TRUE
);
148 MmUnlockAddressSpace(AddressSpace
);
149 if (Address
< MmSystemRangeStart
)
151 ExReleaseRundownProtection(&Process
->RundownProtect
);
152 ObDereferenceObject(Process
);
154 return(STATUS_UNSUCCESSFUL
);
158 * Release locks now we have a page op.
160 MmUnlockAddressSpace(AddressSpace
);
163 * Do the actual page out work.
165 Status
= MmPageOutVirtualMemory(AddressSpace
, MemoryArea
,
170 KeBugCheck(MEMORY_MANAGEMENT
);
173 if (Address
< MmSystemRangeStart
)
175 ExReleaseRundownProtection(&Process
->RundownProtect
);
176 ObDereferenceObject(Process
);
183 MmSetCleanAllRmaps(PFN_NUMBER Page
)
185 PMM_RMAP_ENTRY current_entry
;
187 ExAcquireFastMutex(&RmapListLock
);
188 current_entry
= MmGetRmapListHeadPage(Page
);
189 if (current_entry
== NULL
)
191 DPRINT1("MmIsDirtyRmap: No rmaps.\n");
192 KeBugCheck(MEMORY_MANAGEMENT
);
194 while (current_entry
!= NULL
)
196 MmSetCleanPage(current_entry
->Process
, current_entry
->Address
);
197 current_entry
= current_entry
->Next
;
199 ExReleaseFastMutex(&RmapListLock
);
204 MmSetDirtyAllRmaps(PFN_NUMBER Page
)
206 PMM_RMAP_ENTRY current_entry
;
208 ExAcquireFastMutex(&RmapListLock
);
209 current_entry
= MmGetRmapListHeadPage(Page
);
210 if (current_entry
== NULL
)
212 DPRINT1("MmIsDirtyRmap: No rmaps.\n");
213 KeBugCheck(MEMORY_MANAGEMENT
);
215 while (current_entry
!= NULL
)
217 MmSetDirtyPage(current_entry
->Process
, current_entry
->Address
);
218 current_entry
= current_entry
->Next
;
220 ExReleaseFastMutex(&RmapListLock
);
225 MmIsDirtyPageRmap(PFN_NUMBER Page
)
227 PMM_RMAP_ENTRY current_entry
;
229 ExAcquireFastMutex(&RmapListLock
);
230 current_entry
= MmGetRmapListHeadPage(Page
);
231 if (current_entry
== NULL
)
233 ExReleaseFastMutex(&RmapListLock
);
236 while (current_entry
!= NULL
)
238 if (MmIsDirtyPage(current_entry
->Process
, current_entry
->Address
))
240 ExReleaseFastMutex(&RmapListLock
);
243 current_entry
= current_entry
->Next
;
245 ExReleaseFastMutex(&RmapListLock
);
251 MmInsertRmap(PFN_NUMBER Page
, PEPROCESS Process
,
254 PMM_RMAP_ENTRY current_entry
;
255 PMM_RMAP_ENTRY new_entry
;
258 Address
= (PVOID
)PAGE_ROUND_DOWN(Address
);
260 new_entry
= ExAllocateFromNPagedLookasideList(&RmapLookasideList
);
261 if (new_entry
== NULL
)
263 KeBugCheck(MEMORY_MANAGEMENT
);
265 new_entry
->Address
= Address
;
266 new_entry
->Process
= (PEPROCESS
)Process
;
269 new_entry
->Caller
= __builtin_return_address(0);
271 new_entry
->Caller
= _ReturnAddress();
275 if (MmGetPfnForProcess(Process
, Address
) != Page
)
277 DPRINT1("Insert rmap (%d, 0x%.8X) 0x%.8X which doesn't match physical "
278 "address 0x%.8X\n", Process
->UniqueProcessId
, Address
,
279 MmGetPfnForProcess(Process
, Address
) << PAGE_SHIFT
,
281 KeBugCheck(MEMORY_MANAGEMENT
);
284 ExAcquireFastMutex(&RmapListLock
);
285 current_entry
= MmGetRmapListHeadPage(Page
);
286 new_entry
->Next
= current_entry
;
288 while (current_entry
)
290 if (current_entry
->Address
== new_entry
->Address
&& current_entry
->Process
== new_entry
->Process
)
292 DbgPrint("MmInsertRmap tries to add a second rmap entry for address %p\n current caller ",
293 current_entry
->Address
);
294 DbgPrint("%p", new_entry
->Caller
);
295 DbgPrint("\n previous caller ");
296 DbgPrint("%p", current_entry
->Caller
);
298 KeBugCheck(MEMORY_MANAGEMENT
);
300 current_entry
= current_entry
->Next
;
303 MmSetRmapListHeadPage(Page
, new_entry
);
304 ExReleaseFastMutex(&RmapListLock
);
307 Process
= PsInitialSystemProcess
;
311 PrevSize
= InterlockedExchangeAddUL(&Process
->Vm
.WorkingSetSize
, PAGE_SIZE
);
312 if (PrevSize
>= Process
->Vm
.PeakWorkingSetSize
)
314 Process
->Vm
.PeakWorkingSetSize
= PrevSize
+ PAGE_SIZE
;
321 MmDeleteAllRmaps(PFN_NUMBER Page
, PVOID Context
,
322 VOID (*DeleteMapping
)(PVOID Context
, PEPROCESS Process
,
325 PMM_RMAP_ENTRY current_entry
;
326 PMM_RMAP_ENTRY previous_entry
;
329 ExAcquireFastMutex(&RmapListLock
);
330 current_entry
= MmGetRmapListHeadPage(Page
);
331 if (current_entry
== NULL
)
333 DPRINT1("MmDeleteAllRmaps: No rmaps.\n");
334 KeBugCheck(MEMORY_MANAGEMENT
);
336 MmSetRmapListHeadPage(Page
, NULL
);
337 ExReleaseFastMutex(&RmapListLock
);
338 while (current_entry
!= NULL
)
340 previous_entry
= current_entry
;
341 current_entry
= current_entry
->Next
;
344 DeleteMapping(Context
, previous_entry
->Process
,
345 previous_entry
->Address
);
347 Process
= previous_entry
->Process
;
348 ExFreeToNPagedLookasideList(&RmapLookasideList
, previous_entry
);
351 Process
= PsInitialSystemProcess
;
355 (void)InterlockedExchangeAddUL(&Process
->Vm
.WorkingSetSize
, -PAGE_SIZE
);
362 MmDeleteRmap(PFN_NUMBER Page
, PEPROCESS Process
,
365 PMM_RMAP_ENTRY current_entry
, previous_entry
;
367 ExAcquireFastMutex(&RmapListLock
);
368 previous_entry
= NULL
;
369 current_entry
= MmGetRmapListHeadPage(Page
);
371 while (current_entry
!= NULL
)
373 if (current_entry
->Process
== (PEPROCESS
)Process
&&
374 current_entry
->Address
== Address
)
376 if (previous_entry
== NULL
)
378 MmSetRmapListHeadPage(Page
, current_entry
->Next
);
382 previous_entry
->Next
= current_entry
->Next
;
384 ExReleaseFastMutex(&RmapListLock
);
385 ExFreeToNPagedLookasideList(&RmapLookasideList
, current_entry
);
388 Process
= PsInitialSystemProcess
;
392 (void)InterlockedExchangeAddUL(&Process
->Vm
.WorkingSetSize
, -PAGE_SIZE
);
396 previous_entry
= current_entry
;
397 current_entry
= current_entry
->Next
;
399 KeBugCheck(MEMORY_MANAGEMENT
);