ReactOS 0.4.16-dev-1146-gc477928
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
64{
65 /* Do it the simple way */
67}
68
73 PVOID Address_,
75{
76 ULONG_PTR StartVpn = (ULONG_PTR)Address_ / PAGE_SIZE;
77 ULONG_PTR EndVpn = ((ULONG_PTR)Address_ + Length - 1) / PAGE_SIZE;
83 PMMVAD_LONG Vad;
84
86 Table = (Process != NULL) ? &Process->VadRoot : &MiRosKernelVadRoot;
87
88 Result = MiCheckForConflictingNode(StartVpn, EndVpn, Table, &Node);
89 if (Result != TableFoundNode)
90 {
91 return NULL;
92 }
93
94 Vad = (PMMVAD_LONG)Node;
95 if (!MI_IS_MEMORY_AREA_VAD(Vad))
96 {
97 /* This is an ARM3 VAD, we don't return it. */
98 return NULL;
99 }
100 else
101 {
103 }
104
106 return MemoryArea;
107}
108
110NTAPI
115{
116 ULONG_PTR StartVpn = (ULONG_PTR)Address / PAGE_SIZE;
117 ULONG_PTR EndVpn = ((ULONG_PTR)Address + Length - 1) / PAGE_SIZE;
122
124 Table = (Process != NULL) ? &Process->VadRoot : &MiRosKernelVadRoot;
125
126 Result = MiCheckForConflictingNode(StartVpn, EndVpn, Table, &Node);
127
128 return (Result != TableFoundNode);
129}
130
131VOID
132NTAPI
134 IN PMM_AVL_TABLE VadRoot);
135
136ULONG
137NTAPI
140);
141
142
143static VOID
146 PMEMORY_AREA marea,
148{
150
152
153 /* Build a lame VAD if this is a user-space allocation */
155 {
156 ASSERT(Process != NULL);
157 if (marea->Type != MEMORY_AREA_OWNED_BY_ARM3)
158 {
159#ifdef NEWCC
160 ASSERT(marea->Type == MEMORY_AREA_SECTION_VIEW || marea->Type == MEMORY_AREA_CACHE);
161#else
163#endif
164
165 /* Insert the VAD */
167 MiInsertVad(&marea->VadNode, &Process->VadRoot);
169 }
170 }
171 else
172 {
173 ASSERT(Process == NULL);
174
176 {
180 }
181
182 /* Insert the VAD */
186 }
187}
188
193 ULONG_PTR Granularity,
194 BOOLEAN TopDown)
195{
197 PMM_AVL_TABLE VadRoot;
200 ULONG_PTR StartingAddress, HighestAddress;
201
203 VadRoot = Process ? &Process->VadRoot : &MiRosKernelVadRoot;
204 if (TopDown)
205 {
206 /* Find an address top-down */
207 HighestAddress = Process ? (ULONG_PTR)MM_HIGHEST_VAD_ADDRESS : (LONG_PTR)-1;
209 HighestAddress,
210 Granularity,
211 VadRoot,
212 &StartingAddress,
213 &Parent);
214 }
215 else
216 {
218 Granularity,
219 VadRoot,
220 &Parent,
221 &StartingAddress);
222 }
223
224 if (Result == TableFoundNode)
225 {
226 return NULL;
227 }
228
229 return (PVOID)StartingAddress;
230}
231
232VOID
233NTAPI
236
237
262 PVOID FreePageContext)
263{
265 PVOID EndAddress;
266
267 /* Make sure we own the address space lock! */
268 ASSERT(CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock.Owner == KeGetCurrentThread());
269
270 /* Check magic */
271 ASSERT(MemoryArea->Magic == 'erAM');
272
274 {
275 PEPROCESS CurrentProcess = PsGetCurrentProcess();
277
278 if ((Process != NULL) && (Process != CurrentProcess))
279 {
281 }
282
285 Address < (ULONG_PTR)EndAddress;
287 {
288 BOOLEAN Dirty = FALSE;
289 SWAPENTRY SwapEntry = 0;
290 PFN_NUMBER Page = 0;
291 BOOLEAN DoFree;
292
294 {
296 /* We'll have to do some cleanup when we're on the page file */
297 DoFree = TRUE;
298 }
299 else if (FreePage == NULL)
300 {
301 DoFree = MmDeletePhysicalMapping(Process, (PVOID)Address, &Dirty, &Page);
302 }
303 else
304 {
305 DoFree = MmDeleteVirtualMapping(Process, (PVOID)Address, &Dirty, &Page);
306 }
307 if (DoFree && (FreePage != NULL))
308 {
309 FreePage(FreePageContext, MemoryArea, (PVOID)Address,
310 Page, SwapEntry, (BOOLEAN)Dirty);
311 }
312 }
313
315 {
317#ifdef NEWCC
318 ASSERT(MemoryArea->Type == MEMORY_AREA_SECTION_VIEW || MemoryArea->Type == MEMORY_AREA_CACHE);
319#else
321#endif
322
323 /* We do not have fake ARM3 memory areas anymore. */
328 }
329 else
330 {
334 }
335
336 if ((Process != NULL) && (Process != CurrentProcess))
337 {
339 }
340 }
341
342#if DBG
343 MemoryArea->Magic = 'daeD';
344#endif
346
347 DPRINT("MmFreeMemoryArea() succeeded\n");
348
349 return STATUS_SUCCESS;
350}
351
380 ULONG Type,
385 ULONG AllocationFlags,
386 ULONG Granularity)
387{
388 ULONG_PTR tmpLength;
390 ULONG_PTR EndingAddress;
391
392 DPRINT("MmCreateMemoryArea(Type 0x%lx, BaseAddress %p, "
393 "*BaseAddress %p, Length %p, AllocationFlags %x, "
394 "Result %p)\n",
395 Type, BaseAddress, *BaseAddress, Length, AllocationFlags,
396 Result);
397
398 /* Is this a static memory area? */
400 {
401 /* Use the static array instead of the pool */
404 }
405 else
406 {
407 /* Allocate the memory area from nonpaged pool */
409 sizeof(MEMORY_AREA),
410 TAG_MAREA);
411 }
412
413 if (!MemoryArea)
414 {
415 DPRINT1("Not enough memory.\n");
416 return STATUS_NO_MEMORY;
417 }
418
420 MemoryArea->Type = Type & ~MEMORY_AREA_STATIC;
421 MemoryArea->Flags = AllocationFlags;
422 MemoryArea->Magic = 'erAM';
426 {
428 }
429
430 if (*BaseAddress == 0)
431 {
432 tmpLength = (ULONG_PTR)MM_ROUND_UP(Length, PAGE_SIZE);
434 tmpLength,
435 Granularity,
436 (AllocationFlags & MEM_TOP_DOWN) == MEM_TOP_DOWN);
437 if ((*BaseAddress) == 0)
438 {
439 DPRINT("No suitable gap\n");
441 return STATUS_NO_MEMORY;
442 }
443
447 }
448 else
449 {
450 EndingAddress = ((ULONG_PTR)*BaseAddress + Length - 1) | (PAGE_SIZE - 1);
452 tmpLength = EndingAddress + 1 - (ULONG_PTR)*BaseAddress;
453
455 {
456 ASSERT(FALSE);
459 }
460
463 {
464 DPRINT("Memory area for user mode address space exceeds MmSystemRangeStart\n");
467 }
468
469 /* No need to check ARM3 owned memory areas, the range MUST be free */
471 {
473 {
474 DPRINT("Memory area already occupied\n");
477 }
478 }
479
483 }
484
486
487 DPRINT("MmCreateMemoryArea() succeeded (%p)\n", *BaseAddress);
488 return STATUS_SUCCESS;
489}
490
491VOID
492NTAPI
495 PMMVAD Vad)
496{
500
501 /* We must be called from MmCleanupAddressSpace and nowhere else!
502 Make sure things are as expected... */
504 ASSERT(Process->VmDeleted == TRUE);
505 ASSERT(((PsGetCurrentThread()->ThreadsProcess == Process) &&
506 (Process->ActiveThreads == 1)) ||
507 (Process->ActiveThreads == 0));
508
511
513 {
515 }
516#ifdef NEWCC
517 else if (MemoryArea->Type == MEMORY_AREA_CACHE)
518 {
520 }
521#endif
522 else
523 {
524 /* There shouldn't be anything else! */
525 ASSERT(FALSE);
526 }
527
528 /* Make sure this worked! */
530}
531/* EOF */
ULONG_PTR PFN_NUMBER
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 STATUS_NO_MEMORY
Definition: d3dkmdt.h:51
#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:33
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:403
PMEMORY_AREA NTAPI MmLocateMemoryAreaByRegion(PMMSUPPORT AddressSpace, PVOID Address_, ULONG_PTR Length)
Definition: marea.c:71
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:379
NTSTATUS NTAPI MmFreeMemoryArea(PMMSUPPORT AddressSpace, PMEMORY_AREA MemoryArea, PMM_FREE_PAGE_FUNC FreePage, PVOID FreePageContext)
Definition: marea.c:258
VOID NTAPI MiInsertVad(IN PMMVAD Vad, IN PMM_AVL_TABLE VadRoot)
Definition: vadnode.c:222
MEMORY_AREA MiStaticMemoryAreas[MI_STATIC_MEMORY_AREAS]
Definition: marea.c:51
ULONG MiStaticMemoryAreaCount
Definition: marea.c:52
PMEMORY_AREA NTAPI MmLocateMemoryAreaByAddress(PMMSUPPORT AddressSpace, PVOID Address)
Definition: marea.c:61
VOID NTAPI MiRosCleanupMemoryArea(PEPROCESS Process, PMMVAD Vad)
Definition: marea.c:493
PVOID NTAPI MmFindGap(PMMSUPPORT AddressSpace, ULONG_PTR Length, ULONG_PTR Granularity, BOOLEAN TopDown)
Definition: marea.c:190
BOOLEAN NTAPI MmIsAddressRangeFree(_In_ PMMSUPPORT AddressSpace, _In_ PVOID Address, _In_ ULONG_PTR Length)
Definition: marea.c:111
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:144
FORCEINLINE VOID MiLockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1268
FORCEINLINE VOID MiUnlockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1197
FORCEINLINE VOID MiUnlockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1242
FORCEINLINE VOID MiUnlockWorkingSet(IN PETHREAD Thread, IN PMMSUPPORT WorkingSet)
Definition: miarm.h:1354
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:593
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:496
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:157
NTSTATUS NTAPI MiRosUnmapViewOfSection(_In_ PEPROCESS Process, _In_ PMEMORY_AREA MemoryArea, _In_ PVOID BaseAddress, _In_ BOOLEAN SkipDebuggerNotify)
Definition: section.c:3602
FORCEINLINE VOID MiLockProcessWorkingSet(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1127
FORCEINLINE VOID MiLockProcessWorkingSetUnsafe(IN PEPROCESS Process, IN PETHREAD Thread)
Definition: miarm.h:1172
#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 _In_
Definition: no_sal2.h:158
#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:252
#define MA_GetStartingAddress(_MemoryArea)
Definition: mm.h:251
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:547
FORCEINLINE PEPROCESS MmGetAddressSpaceOwner(IN PMMSUPPORT AddressSpace)
Definition: mm.h:1716
#define MI_IS_MEMORY_AREA_VAD(Vad)
Definition: mm.h:272
#define MEMORY_AREA_SECTION_VIEW
Definition: mm.h:93
#define MI_SET_ROSMM_VAD(Vad)
Definition: mm.h:273
#define MI_SET_MEMORY_AREA_VAD(Vad)
Definition: mm.h:271
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_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
#define STATUS_SUCCESS
Definition: shellext.h:65
#define DPRINT
Definition: sndvol32.h:73
ULONG Flags
Definition: mm.h:259
ULONG Magic
Definition: mm.h:261
BOOLEAN DeleteInProgress
Definition: mm.h:260
ULONG Type
Definition: mm.h:258
MMVAD VadNode
Definition: mm.h:256
union _MMADDRESS_NODE::@2709 u1
struct _MMADDRESS_NODE * Parent
Definition: mmtypes.h:649
ULONG_PTR Protection
Definition: mmtypes.h:696
ULONG_PTR EndingVpn
Definition: mmtypes.h:730
ULONG_PTR StartingVpn
Definition: mmtypes.h:729
union _MMVAD::@2711 u
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:106
#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:386
_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