ReactOS 0.4.15-dev-7674-gc0b4db1
marea.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 *
18 *
19 * PROJECT: ReactOS kernel
20 * FILE: ntoskrnl/mm/marea.c
21 * PURPOSE: Implements memory areas
22 *
23 * PROGRAMMERS: Rex Jolliff
24 * David Welch
25 * Eric Kohl
26 * Philip Susi
27 * Casper Hornstrup
28 * Eric Kohl
29 * Ge van Geldorp
30 * Royce Mitchell III
31 * Aleksey Bragin
32 * Jason Filby
33 * Thomas Weidenmueller
34 * Gunnar Andre' Dalsnes
35 * Mike Nordell
36 * Alex Ionescu
37 * Filip Navara
38 * Herve Poussineau
39 * Steven Edwards
40 */
41
42/* INCLUDES *****************************************************************/
43
44#include <ntoskrnl.h>
45#define NDEBUG
46#include <cache/section/newmm.h>
47#include <debug.h>
48
49#include "ARM3/miarm.h"
50
53
56
57/* FUNCTIONS *****************************************************************/
58
62 PVOID Address_)
63{
64 ULONG_PTR StartVpn = (ULONG_PTR)Address_ / PAGE_SIZE;
70 PMMVAD_LONG Vad;
71
73 Table = (Process != NULL) ? &Process->VadRoot : &MiRosKernelVadRoot;
74
75 Result = MiCheckForConflictingNode(StartVpn, StartVpn, Table, &Node);
76 if (Result != TableFoundNode)
77 {
78 return NULL;
79 }
80
81 Vad = (PMMVAD_LONG)Node;
82 if (Vad->u.VadFlags.Spare == 0)
83 {
84 /* Check if this is VM VAD */
85 if (Vad->ControlArea == NULL)
86 {
87 /* We store the reactos MEMORY_AREA here */
89 }
90 else
91 {
92 /* This is a section VAD. Store the MAREA here for now */
94 }
95 }
96 else
97 {
99 }
100
101 return MemoryArea;
102}
103
105NTAPI
108 PVOID Address_,
110{
111 ULONG_PTR StartVpn = (ULONG_PTR)Address_ / PAGE_SIZE;
112 ULONG_PTR EndVpn = ((ULONG_PTR)Address_ + Length - 1) / PAGE_SIZE;
118 PMMVAD_LONG Vad;
119
121 Table = (Process != NULL) ? &Process->VadRoot : &MiRosKernelVadRoot;
122
123 Result = MiCheckForConflictingNode(StartVpn, EndVpn, Table, &Node);
124 if (Result != TableFoundNode)
125 {
126 return NULL;
127 }
128
129 Vad = (PMMVAD_LONG)Node;
130 if (Vad->u.VadFlags.Spare == 0)
131 {
132 /* Check if this is VM VAD */
133 if (Vad->ControlArea == NULL)
134 {
135 /* We store the reactos MEMORY_AREA here */
137 }
138 else
139 {
140 /* This is a section VAD. Store the MAREA here for now */
142 }
143 }
144 else
145 {
147 }
148
150 return MemoryArea;
151}
152
153VOID
154NTAPI
156 IN PMM_AVL_TABLE VadRoot);
157
158ULONG
159NTAPI
162);
163
164
165static VOID
168 PMEMORY_AREA marea,
170{
172
173 marea->VadNode.u.VadFlags.Spare = 1;
175
176 /* Build a lame VAD if this is a user-space allocation */
178 {
179 ASSERT(Process != NULL);
180 if (marea->Type != MEMORY_AREA_OWNED_BY_ARM3)
181 {
182#ifdef NEWCC
183 ASSERT(marea->Type == MEMORY_AREA_SECTION_VIEW || marea->Type == MEMORY_AREA_CACHE);
184#else
186#endif
187
188 /* Insert the VAD */
190 MiInsertVad(&marea->VadNode, &Process->VadRoot);
192 marea->Vad = &marea->VadNode;
193 }
194 }
195 else
196 {
197 ASSERT(Process == NULL);
198
200 {
204 }
205
206 /* Insert the VAD */
210 marea->Vad = NULL;
211 }
212}
213
218 ULONG_PTR Granularity,
219 BOOLEAN TopDown)
220{
222 PMM_AVL_TABLE VadRoot;
225 ULONG_PTR StartingAddress, HighestAddress;
226
228 VadRoot = Process ? &Process->VadRoot : &MiRosKernelVadRoot;
229 if (TopDown)
230 {
231 /* Find an address top-down */
232 HighestAddress = Process ? (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS : (LONG_PTR)-1;
234 HighestAddress,
235 Granularity,
236 VadRoot,
237 &StartingAddress,
238 &Parent);
239 }
240 else
241 {
243 Granularity,
244 VadRoot,
245 &Parent,
246 &StartingAddress);
247 }
248
249 if (Result == TableFoundNode)
250 {
251 return NULL;
252 }
253
254 return (PVOID)StartingAddress;
255}
256
257VOID
258NTAPI
261
262
287 PVOID FreePageContext)
288{
290 PVOID EndAddress;
291
292 /* Make sure we own the address space lock! */
293 ASSERT(CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock.Owner == KeGetCurrentThread());
294
295 /* Check magic */
296 ASSERT(MemoryArea->Magic == 'erAM');
297
299 {
300 PEPROCESS CurrentProcess = PsGetCurrentProcess();
302
303 if ((Process != NULL) && (Process != CurrentProcess))
304 {
306 }
307
310 Address < (ULONG_PTR)EndAddress;
312 {
313 BOOLEAN Dirty = FALSE;
314 SWAPENTRY SwapEntry = 0;
315 PFN_NUMBER Page = 0;
316 BOOLEAN DoFree;
317
319 {
321 /* We'll have to do some cleanup when we're on the page file */
322 DoFree = TRUE;
323 }
324 else if (FreePage == NULL)
325 {
326 DoFree = MmDeletePhysicalMapping(Process, (PVOID)Address, &Dirty, &Page);
327 }
328 else
329 {
330 DoFree = MmDeleteVirtualMapping(Process, (PVOID)Address, &Dirty, &Page);
331 }
332 if (DoFree && (FreePage != NULL))
333 {
334 FreePage(FreePageContext, MemoryArea, (PVOID)Address,
335 Page, SwapEntry, (BOOLEAN)Dirty);
336 }
337 }
338
339 //if (MemoryArea->VadNode.StartingVpn < (ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT
340 if (MemoryArea->Vad)
341 {
343#ifdef NEWCC
344 ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW || MemoryArea->Type == MEMORY_AREA_CACHE);
345#else
347#endif
348
349 /* MmCleanProcessAddressSpace might have removed it (and this would be MmDeleteProcessAddressSpace) */
351 if (((PMMVAD)MemoryArea->Vad)->u.VadFlags.Spare == 1)
352 {
356 }
357
359 }
360 else
361 {
365 }
366
367 if ((Process != NULL) && (Process != CurrentProcess))
368 {
370 }
371 }
372
373#if DBG
374 MemoryArea->Magic = 'daeD';
375#endif
377
378 DPRINT("MmFreeMemoryArea() succeeded\n");
379
380 return STATUS_SUCCESS;
381}
382
411 ULONG Type,
416 ULONG AllocationFlags,
417 ULONG Granularity)
418{
419 ULONG_PTR tmpLength;
421 ULONG_PTR EndingAddress;
422
423 DPRINT("MmCreateMemoryArea(Type 0x%lx, BaseAddress %p, "
424 "*BaseAddress %p, Length %p, AllocationFlags %x, "
425 "Result %p)\n",
426 Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
427 Result);
428
429 /* Is this a static memory area? */
431 {
432 /* Use the static array instead of the pool */
435 }
436 else
437 {
438 /* Allocate the memory area from nonpaged pool */
440 sizeof(MEMORY_AREA),
441 TAG_MAREA);
442 }
443
444 if (!MemoryArea)
445 {
446 DPRINT1("Not enough memory.\n");
447 return STATUS_NO_MEMORY;
448 }
449
451 MemoryArea->Type = Type & ~MEMORY_AREA_STATIC;
452 MemoryArea->Flags = AllocationFlags;
453 MemoryArea->Magic = 'erAM';
455
456 if (*BaseAddress == 0)
457 {
458 tmpLength = (ULONG_PTR)MM_ROUND_UP(Length, PAGE_SIZE);
460 tmpLength,
461 Granularity,
462 (AllocationFlags & MEM_TOP_DOWN) == MEM_TOP_DOWN);
463 if ((*BaseAddress) == 0)
464 {
465 DPRINT("No suitable gap\n");
467 return STATUS_NO_MEMORY;
468 }
469
473 }
474 else
475 {
476 EndingAddress = ((ULONG_PTR)*BaseAddress + Length - 1) | (PAGE_SIZE - 1);
478 tmpLength = EndingAddress + 1 - (ULONG_PTR)*BaseAddress;
479
481 {
482 ASSERT(FALSE);
485 }
486
489 {
490 DPRINT("Memory area for user mode address space exceeds MmSystemRangeStart\n");
493 }
494
495 /* No need to check ARM3 owned memory areas, the range MUST be free */
497 {
500 tmpLength) != NULL)
501 {
502 DPRINT("Memory area already occupied\n");
505 }
506 }
507
511 }
512
514
515 DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
516 return STATUS_SUCCESS;
517}
518
519VOID
520NTAPI
523 PMMVAD Vad)
524{
528
529 /* We must be called from MmCleanupAddressSpace and nowhere else!
530 Make sure things are as expected... */
532 ASSERT(Process->VmDeleted == TRUE);
533 ASSERT(((PsGetCurrentThread()->ThreadsProcess == Process) &&
534 (Process->ActiveThreads == 1)) ||
535 (Process->ActiveThreads == 0));
536
539
541 {
543 }
544#ifdef NEWCC
545 else if (MemoryArea->Type == MEMORY_AREA_CACHE)
546 {
548 }
549#endif
550 else
551 {
552 /* There shouldn't be anything else! */
553 ASSERT(FALSE);
554 }
555
556 /* Make sure this worked! */
558}
559/* EOF */
unsigned char BOOLEAN
Type
Definition: Type.h:7
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn UINT32 *TableIdx UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 ACPI_BUFFER *RetPathPtr ACPI_OBJECT_HANDLER void *Data ACPI_OBJECT_HANDLER void **Data ACPI_STRING ACPI_OBJECT_LIST ACPI_BUFFER *ReturnObjectBuffer ACPI_DEVICE_INFO **ReturnBuffer ACPI_HANDLE Parent
Definition: acpixf.h:732
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
union node Node
Definition: types.h:1255
#define ULONG_PTR
Definition: config.h:101
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define PAGE_SHIFT
Definition: env_spec_w32.h:45
#define NonPagedPool
Definition: env_spec_w32.h:307
_Must_inspect_result_ _In_ PLARGE_INTEGER _In_ PLARGE_INTEGER _In_ ULONG _In_ PFILE_OBJECT _In_ PVOID Process
Definition: fsrtlfuncs.h:223
Status
Definition: gdiplustypes.h:25
ASMGENDATA Table[]
Definition: genincdata.c:61
#define KeGetCurrentThread
Definition: hal.h:55
VOID NTAPI MiRemoveNode(IN PMMADDRESS_NODE Node, IN PMM_AVL_TABLE Table)
Definition: vadnode.c:440
PMEMORY_AREA NTAPI MmLocateMemoryAreaByRegion(PMMSUPPORT AddressSpace, PVOID Address_, ULONG_PTR Length)
Definition: marea.c:106
MM_AVL_TABLE MiRosKernelVadRoot
Definition: marea.c:54
NTSTATUS NTAPI MmCreateMemoryArea(PMMSUPPORT AddressSpace, ULONG Type, PVOID *BaseAddress, ULONG_PTR Length, ULONG Protect, PMEMORY_AREA *Result, ULONG AllocationFlags, ULONG Granularity)
Definition: marea.c:410
NTSTATUS NTAPI MmFreeMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_FREE_PAGE_FUNC FreePage, PVOID FreePageContext)
Definition: marea.c:283
VOID NTAPI MiInsertVad(IN PMMVAD Vad, IN PMM_AVL_TABLE VadRoot)
Definition: vadnode.c:259
MEMORY_AREA MiStaticMemoryAreas[MI_STATIC_MEMORY_AREAS]
Definition: marea.c:51
ULONG MiStaticMemoryAreaCount
Definition: marea.c:52
VOID NTAPI MiRosCleanupMemoryArea(PEPROCESS Process, PMMVAD Vad)
Definition: marea.c:521
PVOID NTAPI MmFindGap(PMMSUPPORT AddressSpace, ULONG_PTR Length, ULONG_PTR Granularity, BOOLEAN TopDown)
Definition: marea.c:215
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address_)
Definition: marea.c:60
BOOLEAN MiRosKernelVadRootInitialized
Definition: marea.c:55
ULONG NTAPI MiMakeProtectionMask(IN ULONG Protect)
Definition: section.c:140
static VOID MmInsertMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA marea, ULONG Protect)
Definition: marea.c:166
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1265
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1194
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1239
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1351
NTSTATUS NTAPI MiRosUnmapViewOfSection(IN PEPROCESS Process, IN PVOID BaseAddress, IN BOOLEAN SkipDebuggerNotify)
Definition: section.c:3589
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeDownTree(IN SIZE_T Length, IN ULONG_PTR BoundaryAddress, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PULONG_PTR Base, OUT PMMADDRESS_NODE *Parent)
Definition: vadnode.c:681
TABLE_SEARCH_RESULT NTAPI MiFindEmptyAddressRangeInTree(IN SIZE_T Length, IN ULONG_PTR Alignment, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *PreviousVad, OUT PULONG_PTR Base)
Definition: vadnode.c:584
TABLE_SEARCH_RESULT NTAPI MiCheckForConflictingNode(IN ULONG_PTR StartVpn, IN ULONG_PTR EndVpn, IN PMM_AVL_TABLE Table, OUT PMMADDRESS_NODE *NodeOrParent)
Definition: vadnode.c:150
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1124
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1169
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID * BaseAddress
Definition: mmfuncs.h:404
struct _MMVAD_LONG * PMMVAD_LONG
_In_ PMEMORY_AREA MemoryArea
Definition: newmm.h:207
NTSTATUS NTAPI MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace, PVOID BaseAddress)
#define MEM_TOP_DOWN
Definition: nt_native.h:1321
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define MM_HIGHEST_VAD_ADDRESS
Definition: mm.h:46
#define MmSystemRangeStart
Definition: mm.h:32
#define MI_STATIC_MEMORY_AREAS
Definition: mm.h:90
#define MM_ROUND_UP(x, s)
Definition: mm.h:128
#define MEMORY_AREA_STATIC
Definition: mm.h:98
BOOLEAN NTAPI MmIsPageSwapEntry(struct _EPROCESS *Process, PVOID Address)
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1306
#define MEMORY_AREA_OWNED_BY_ARM3
Definition: mm.h:97
struct _MEMORY_AREA * PMEMORY_AREA
ULONG_PTR SWAPENTRY
Definition: mm.h:57
#define MA_GetEndingAddress(_MemoryArea)
Definition: mm.h:245
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:244
VOID NTAPI MmDeletePageFileMapping(struct _EPROCESS *Process, PVOID Address, SWAPENTRY *SwapEntry)
VOID(* PMM_FREE_PAGE_FUNC)(PVOID Context, PMEMORY_AREA MemoryArea, PVOID Address, PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
Definition: mm.h:527
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1711
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
MMSUPPORT MmSystemCacheWs
Definition: init.c:55
VOID NTAPI MmDeleteVirtualMapping(IN PEPROCESS Process, IN PVOID Address, OUT PBOOLEAN WasDirty, OUT PPFN_NUMBER Page)
Definition: page.c:177
#define STATUS_NO_MEMORY
Definition: ntstatus.h:260
#define STATUS_ACCESS_VIOLATION
Definition: ntstatus.h:242
#define STATUS_CONFLICTING_ADDRESSES
Definition: ntstatus.h:261
static WCHAR Address[46]
Definition: ping.c:68
VOID NTAPI KeDetachProcess(VOID)
Definition: procobj.c:621
VOID NTAPI KeAttachProcess(IN PKPROCESS Process)
Definition: procobj.c:582
ULONG PFN_NUMBER
Definition: ke.h:9
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:71
PVOID Vad
Definition: mm.h:255
ULONG Flags
Definition: mm.h:252
ULONG Magic
Definition: mm.h:254
BOOLEAN DeleteInProgress
Definition: mm.h:253
ULONG Type
Definition: mm.h:251
MMVAD VadNode
Definition: mm.h:249
union _MMADDRESS_NODE::@2605 u1
struct _MMADDRESS_NODE * Parent
Definition: mmtypes.h:649
ULONG_PTR Protection
Definition: mmtypes.h:696
ULONG_PTR Spare
Definition: mmtypes.h:697
PMMPTE FirstPrototypePte
Definition: mmtypes.h:766
PVOID Banked
Definition: mmtypes.h:780
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:763
union _MMVAD_LONG::@2610 u
PCONTROL_AREA ControlArea
Definition: mmtypes.h:765
union _MMVAD_LONG::@2613 u4
ULONG_PTR EndingVpn
Definition: mmtypes.h:730
union _MMVAD::@2607 u
ULONG_PTR StartingVpn
Definition: mmtypes.h:729
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:734
ULONG_PTR Unused
Definition: mmtypes.h:664
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:662
#define TAG_MAREA
Definition: tag.h:107
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
#define IN
Definition: typedefs.h:39
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t ULONG
Definition: typedefs.h:59
#define ALIGN_DOWN_POINTER_BY(ptr, align)
Definition: umtypes.h:82
Definition: dlist.c:348
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:409
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
@ FreePage
Definition: ketypes.h:416
#define PsGetCurrentProcess
Definition: psfuncs.h:17
TABLE_SEARCH_RESULT
Definition: rtltypes.h:373
_In_ HANDLE _Outptr_result_bytebuffer_ ViewSize PVOID _In_ ULONG_PTR _In_ SIZE_T _Inout_opt_ PLARGE_INTEGER _Inout_ PSIZE_T _In_ SECTION_INHERIT _In_ ULONG _In_ ULONG Protect
Definition: zwfuncs.h:221