ReactOS 0.4.15-dev-6067-g0b695a6
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);
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 &&
304 Process != CurrentProcess)
305 {
307 }
308
311 Address < (ULONG_PTR)EndAddress;
313 {
314 BOOLEAN Dirty = FALSE;
315 SWAPENTRY SwapEntry = 0;
316 PFN_NUMBER Page = 0;
317 BOOLEAN DoFree;
318
320 {
322 /* We'll have to do some cleanup when we're on the page file */
323 DoFree = TRUE;
324 }
325 else
326 {
327 DoFree = MmDeleteVirtualMapping(Process, (PVOID)Address, &Dirty, &Page);
328 }
329 if (DoFree && (FreePage != NULL))
330 {
331 FreePage(FreePageContext, MemoryArea, (PVOID)Address,
332 Page, SwapEntry, (BOOLEAN)Dirty);
333 }
334 }
335
336 if (Process != NULL &&
337 Process != CurrentProcess)
338 {
340 }
341
342 //if (MemoryArea->VadNode.StartingVpn < (ULONG_PTR)MmSystemRangeStart >> PAGE_SHIFT
343 if (MemoryArea->Vad)
344 {
346#ifdef NEWCC
347 ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW || MemoryArea->Type == MEMORY_AREA_CACHE);
348#else
350#endif
351
352 /* MmCleanProcessAddressSpace might have removed it (and this would be MmDeleteProcessAdressSpace) */
354 if (((PMMVAD)MemoryArea->Vad)->u.VadFlags.Spare == 1)
355 {
357 }
358
360 }
361 else
362 {
364 }
365 }
366
367#if DBG
368 MemoryArea->Magic = 'daeD';
369#endif
371
372 DPRINT("MmFreeMemoryArea() succeeded\n");
373
374 return STATUS_SUCCESS;
375}
376
405 ULONG Type,
410 ULONG AllocationFlags,
411 ULONG Granularity)
412{
413 ULONG_PTR tmpLength;
415 ULONG_PTR EndingAddress;
416
417 DPRINT("MmCreateMemoryArea(Type 0x%lx, BaseAddress %p, "
418 "*BaseAddress %p, Length %p, AllocationFlags %x, "
419 "Result %p)\n",
420 Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
421 Result);
422
423 /* Is this a static memory area? */
425 {
426 /* Use the static array instead of the pool */
429 }
430 else
431 {
432 /* Allocate the memory area from nonpaged pool */
434 sizeof(MEMORY_AREA),
435 TAG_MAREA);
436 }
437
438 if (!MemoryArea)
439 {
440 DPRINT1("Not enough memory.\n");
441 return STATUS_NO_MEMORY;
442 }
443
445 MemoryArea->Type = Type & ~MEMORY_AREA_STATIC;
446 MemoryArea->Flags = AllocationFlags;
447 MemoryArea->Magic = 'erAM';
449
450 if (*BaseAddress == 0)
451 {
452 tmpLength = (ULONG_PTR)MM_ROUND_UP(Length, PAGE_SIZE);
454 tmpLength,
455 Granularity,
456 (AllocationFlags & MEM_TOP_DOWN) == MEM_TOP_DOWN);
457 if ((*BaseAddress) == 0)
458 {
459 DPRINT("No suitable gap\n");
461 return STATUS_NO_MEMORY;
462 }
463
467 }
468 else
469 {
470 EndingAddress = ((ULONG_PTR)*BaseAddress + Length - 1) | (PAGE_SIZE - 1);
472 tmpLength = EndingAddress + 1 - (ULONG_PTR)*BaseAddress;
473
475 {
476 ASSERT(FALSE);
479 }
480
483 {
484 DPRINT("Memory area for user mode address space exceeds MmSystemRangeStart\n");
487 }
488
489 /* No need to check ARM3 owned memory areas, the range MUST be free */
491 {
494 tmpLength) != NULL)
495 {
496 DPRINT("Memory area already occupied\n");
499 }
500 }
501
505 }
506
508
509 DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
510 return STATUS_SUCCESS;
511}
512
513VOID
514NTAPI
517 PMMVAD Vad)
518{
522
523 /* We must be called from MmCleanupAddressSpace and nowhere else!
524 Make sure things are as expected... */
526 ASSERT(Process->VmDeleted == TRUE);
527 ASSERT(((PsGetCurrentThread()->ThreadsProcess == Process) &&
528 (Process->ActiveThreads == 1)) ||
529 (Process->ActiveThreads == 0));
530
533
535 {
537 }
538#ifdef NEWCC
539 else if (MemoryArea->Type == MEMORY_AREA_CACHE)
540 {
542 }
543#endif
544 else
545 {
546 /* There shouldn't be anything else! */
547 ASSERT(FALSE);
548 }
549
550 /* Make sure this worked! */
552}
553/* 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:360
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:404
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:183
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:515
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 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:3567
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:597
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:502
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:78
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:1298
#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:1673
#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::@2586 u1
struct _MMADDRESS_NODE * Parent
Definition: mmtypes.h:646
ULONG_PTR Protection
Definition: mmtypes.h:693
ULONG_PTR Spare
Definition: mmtypes.h:694
PMMPTE FirstPrototypePte
Definition: mmtypes.h:763
PVOID Banked
Definition: mmtypes.h:777
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:760
PCONTROL_AREA ControlArea
Definition: mmtypes.h:762
union _MMVAD_LONG::@2591 u
union _MMVAD_LONG::@2594 u4
ULONG_PTR EndingVpn
Definition: mmtypes.h:727
ULONG_PTR StartingVpn
Definition: mmtypes.h:726
union _MMVAD::@2588 u
MMVAD_FLAGS VadFlags
Definition: mmtypes.h:731
ULONG_PTR Unused
Definition: mmtypes.h:661
MMADDRESS_NODE BalancedRoot
Definition: mmtypes.h:659
#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:426
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
@ FreePage
Definition: ketypes.h:404
#define PsGetCurrentProcess
Definition: psfuncs.h:17
@ TableFoundNode
Definition: rtltypes.h:364
enum _TABLE_SEARCH_RESULT TABLE_SEARCH_RESULT
_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