Removed obsolete header files
[reactos.git] / reactos / ntoskrnl / mm / marea.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/marea.c
5 * PURPOSE: Implements memory areas
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/mm.h>
15 #include <internal/ps.h>
16 #include <internal/pool.h>
17
18 #define NDEBUG
19 #include <internal/debug.h>
20
21 /* GLOBALS *******************************************************************/
22
23 #define TAG_MAREA TAG('M', 'A', 'R', 'E')
24
25 /* FUNCTIONS *****************************************************************/
26
27 VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead)
28 {
29 PLIST_ENTRY current_entry;
30 MEMORY_AREA* current;
31
32 DbgPrint("MmDumpMemoryAreas()\n");
33
34 current_entry = ListHead->Flink;
35 while (current_entry!=ListHead)
36 {
37 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
38 DbgPrint("Base %x Length %x End %x Attributes %x Flink %x\n",
39 current->BaseAddress,current->Length,
40 current->BaseAddress+current->Length,current->Attributes,
41 current->Entry.Flink);
42 current_entry = current_entry->Flink;
43 }
44 DbgPrint("Finished MmDumpMemoryAreas()\n");
45 }
46
47 MEMORY_AREA* MmOpenMemoryAreaByAddress(PMADDRESS_SPACE AddressSpace,
48 PVOID Address)
49 {
50 PLIST_ENTRY current_entry;
51 MEMORY_AREA* current;
52 PLIST_ENTRY previous_entry;
53
54 DPRINT("MmOpenMemoryAreaByAddress(AddressSpace %x, Address %x)\n",
55 AddressSpace, Address);
56
57 // MmDumpMemoryAreas(&AddressSpace->MAreaListHead);
58
59 previous_entry = &AddressSpace->MAreaListHead;
60 current_entry = AddressSpace->MAreaListHead.Flink;
61 while (current_entry != &AddressSpace->MAreaListHead)
62 {
63 current = CONTAINING_RECORD(current_entry,
64 MEMORY_AREA,
65 Entry);
66 DPRINT("Scanning %x BaseAddress %x Length %x\n",
67 current, current->BaseAddress, current->Length);
68 assert(current_entry->Blink->Flink == current_entry);
69 if (current_entry->Flink->Blink != current_entry)
70 {
71 DPRINT1("BaseAddress %x\n", current->BaseAddress);
72 DPRINT1("current_entry->Flink %x ", current_entry->Flink);
73 DPRINT1("&current_entry->Flink %x\n",
74 &current_entry->Flink);
75 DPRINT1("current_entry->Flink->Blink %x\n",
76 current_entry->Flink->Blink);
77 DPRINT1("&current_entry->Flink->Blink %x\n",
78 &current_entry->Flink->Blink);
79 DPRINT1("&current_entry->Flink %x\n",
80 &current_entry->Flink);
81 }
82 assert(current_entry->Flink->Blink == current_entry);
83 assert(previous_entry->Flink == current_entry);
84 if (current->BaseAddress <= Address &&
85 (current->BaseAddress + current->Length) > Address)
86 {
87 DPRINT("%s() = %x\n",__FUNCTION__,current);
88 return(current);
89 }
90 if (current->BaseAddress > Address)
91 {
92 DPRINT("%s() = NULL\n",__FUNCTION__);
93 return(NULL);
94 }
95 previous_entry = current_entry;
96 current_entry = current_entry->Flink;
97 }
98 DPRINT("%s() = NULL\n",__FUNCTION__);
99 return(NULL);
100 }
101
102 MEMORY_AREA* MmOpenMemoryAreaByRegion(PMADDRESS_SPACE AddressSpace,
103 PVOID Address,
104 ULONG Length)
105 {
106 PLIST_ENTRY current_entry;
107 MEMORY_AREA* current;
108 ULONG Extent;
109
110 DPRINT("MmOpenMemoryByRegion(AddressSpace %x, Address %x, Length %x)\n",
111 AddressSpace, Address, Length);
112
113 current_entry = AddressSpace->MAreaListHead.Flink;
114 while (current_entry != &AddressSpace->MAreaListHead)
115 {
116 current = CONTAINING_RECORD(current_entry,
117 MEMORY_AREA,
118 Entry);
119 DPRINT("current->BaseAddress %x current->Length %x\n",
120 current->BaseAddress,current->Length);
121 if (current->BaseAddress >= Address &&
122 current->BaseAddress < (Address+Length))
123 {
124 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
125 current);
126 return(current);
127 }
128 Extent = (ULONG)current->BaseAddress + current->Length;
129 if (Extent > (ULONG)Address &&
130 Extent < (ULONG)(Address+Length))
131 {
132 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
133 current);
134 return(current);
135 }
136 if (current->BaseAddress <= Address &&
137 Extent >= (ULONG)(Address+Length))
138 {
139 DPRINT("Finished MmOpenMemoryAreaByRegion() = %x\n",
140 current);
141 return(current);
142 }
143 if (current->BaseAddress >= (Address+Length))
144 {
145 DPRINT("Finished MmOpenMemoryAreaByRegion()= NULL\n",0);
146 return(NULL);
147 }
148 current_entry = current_entry->Flink;
149 }
150 DPRINT("Finished MmOpenMemoryAreaByRegion() = NULL\n",0);
151 return(NULL);
152 }
153
154 static VOID MmInsertMemoryArea(PMADDRESS_SPACE AddressSpace,
155 MEMORY_AREA* marea)
156 {
157 PLIST_ENTRY ListHead;
158 PLIST_ENTRY current_entry;
159 PLIST_ENTRY inserted_entry = &marea->Entry;
160 MEMORY_AREA* current;
161 MEMORY_AREA* next;
162
163 DPRINT("MmInsertMemoryArea(marea %x)\n", marea);
164 DPRINT("marea->BaseAddress %x\n", marea->BaseAddress);
165 DPRINT("marea->Length %x\n", marea->Length);
166
167 ListHead = &AddressSpace->MAreaListHead;
168
169 current_entry = ListHead->Flink;
170 CHECKPOINT;
171 if (IsListEmpty(ListHead))
172 {
173 CHECKPOINT;
174 InsertHeadList(ListHead,&marea->Entry);
175 DPRINT("Inserting at list head\n");
176 CHECKPOINT;
177 return;
178 }
179 CHECKPOINT;
180 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
181 CHECKPOINT;
182 if (current->BaseAddress > marea->BaseAddress)
183 {
184 CHECKPOINT;
185 InsertHeadList(ListHead,&marea->Entry);
186 DPRINT("Inserting at list head\n");
187 CHECKPOINT;
188 return;
189 }
190 CHECKPOINT;
191 while (current_entry->Flink!=ListHead)
192 {
193 // CHECKPOINT;
194 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
195 next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
196 // assert(current->BaseAddress != marea->BaseAddress);
197 // assert(next->BaseAddress != marea->BaseAddress);
198 if (current->BaseAddress < marea->BaseAddress &&
199 current->Entry.Flink==ListHead)
200 {
201 DPRINT("Insert after %x\n", current_entry);
202 current_entry->Flink = inserted_entry;
203 inserted_entry->Flink=ListHead;
204 inserted_entry->Blink=current_entry;
205 ListHead->Blink = inserted_entry;
206 return;
207 }
208 if (current->BaseAddress < marea->BaseAddress &&
209 next->BaseAddress > marea->BaseAddress)
210 {
211 DPRINT("Inserting before %x\n", current_entry);
212 inserted_entry->Flink = current_entry->Flink;
213 inserted_entry->Blink = current_entry;
214 inserted_entry->Flink->Blink = inserted_entry;
215 current_entry->Flink=inserted_entry;
216 return;
217 }
218 current_entry = current_entry->Flink;
219 }
220 CHECKPOINT;
221 DPRINT("Inserting at list tail\n");
222 InsertTailList(ListHead,inserted_entry);
223 }
224
225 static PVOID MmFindGap(PMADDRESS_SPACE AddressSpace,
226 ULONG Length)
227 {
228 PLIST_ENTRY ListHead;
229 PLIST_ENTRY current_entry;
230 MEMORY_AREA* current;
231 MEMORY_AREA* next;
232 ULONG Gap;
233
234 DPRINT("MmFindGap(Length %x)\n",Length);
235
236 ListHead = &AddressSpace->MAreaListHead;
237
238 current_entry = ListHead->Flink;
239 while (current_entry->Flink!=ListHead)
240 {
241 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
242 next = CONTAINING_RECORD(current_entry->Flink,MEMORY_AREA,Entry);
243 DPRINT("current %x current->BaseAddress %x ",current,
244 current->BaseAddress);
245 DPRINT("current->Length %x\n",current->Length);
246 DPRINT("next %x next->BaseAddress %x ",next,next->BaseAddress);
247 Gap = (next->BaseAddress ) -(current->BaseAddress + current->Length);
248 DPRINT("Base %x Gap %x\n",current->BaseAddress,Gap);
249 if (Gap >= Length)
250 {
251 return(current->BaseAddress + PAGE_ROUND_UP(current->Length));
252 }
253 current_entry = current_entry->Flink;
254 }
255
256 if (current_entry == ListHead)
257 {
258 return((PVOID)AddressSpace->LowestAddress);
259 }
260
261 current = CONTAINING_RECORD(current_entry,MEMORY_AREA,Entry);
262 //DbgPrint("current %x returning %x\n",current,current->BaseAddress+
263 // current->Length);
264 return(current->BaseAddress + PAGE_ROUND_UP(current->Length));
265 }
266
267 NTSTATUS MmInitMemoryAreas(VOID)
268 /*
269 * FUNCTION: Initialize the memory area list
270 */
271 {
272 DPRINT("MmInitMemoryAreas()\n",0);
273 return(STATUS_SUCCESS);
274 }
275
276 NTSTATUS
277 MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
278 PVOID BaseAddress,
279 ULONG Length,
280 VOID (*FreePage)(PVOID Context, PVOID Address,
281 ULONG PhysAddr),
282 PVOID FreePageContext)
283 {
284 MEMORY_AREA* MemoryArea;
285 ULONG i;
286
287 DPRINT("MmFreeMemoryArea(AddressSpace %x, BaseAddress %x, Length %x,"
288 "FreePages %d)\n",AddressSpace,BaseAddress,Length,FreePages);
289
290 MemoryArea = MmOpenMemoryAreaByAddress(AddressSpace,
291 BaseAddress);
292 if (MemoryArea == NULL)
293 {
294 KeBugCheck(0);
295 return(STATUS_UNSUCCESSFUL);
296 }
297 for (i=0; i<(PAGE_ROUND_UP(MemoryArea->Length)/PAGESIZE); i++)
298 {
299 ULONG PhysAddr;
300
301 PhysAddr =
302 MmGetPhysicalAddressForProcess(AddressSpace->Process,
303 MemoryArea->BaseAddress + (i*PAGESIZE));
304 MmDeleteVirtualMapping(AddressSpace->Process,
305 MemoryArea->BaseAddress + (i*PAGESIZE),
306 FALSE);
307 if (FreePage != NULL)
308 {
309 FreePage(FreePageContext,
310 MemoryArea->BaseAddress + (i * PAGESIZE), PhysAddr);
311 }
312 }
313
314 RemoveEntryList(&MemoryArea->Entry);
315 ExFreePool(MemoryArea);
316
317 DPRINT("MmFreeMemoryArea() succeeded\n");
318
319 return(STATUS_SUCCESS);
320 }
321
322 PMEMORY_AREA MmSplitMemoryArea(PEPROCESS Process,
323 PMADDRESS_SPACE AddressSpace,
324 PMEMORY_AREA OriginalMemoryArea,
325 PVOID BaseAddress,
326 ULONG Length,
327 ULONG NewType,
328 ULONG NewAttributes)
329 {
330 PMEMORY_AREA Result;
331 PMEMORY_AREA Split;
332
333 Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
334 TAG_MAREA);
335 RtlZeroMemory(Result,sizeof(MEMORY_AREA));
336 Result->Type = NewType;
337 Result->BaseAddress = BaseAddress;
338 Result->Length = Length;
339 Result->Attributes = NewAttributes;
340 Result->LockCount = 0;
341 Result->Process = Process;
342
343 if (BaseAddress == OriginalMemoryArea->BaseAddress)
344 {
345 OriginalMemoryArea->BaseAddress = BaseAddress + Length;
346 OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
347 MmInsertMemoryArea(AddressSpace, Result);
348 return(Result);
349 }
350 if ((BaseAddress + Length) ==
351 (OriginalMemoryArea->BaseAddress + OriginalMemoryArea->Length))
352 {
353 OriginalMemoryArea->Length = OriginalMemoryArea->Length - Length;
354 MmInsertMemoryArea(AddressSpace, Result);
355
356 return(Result);
357 }
358
359 Split = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
360 TAG_MAREA);
361 RtlCopyMemory(Split,OriginalMemoryArea,sizeof(MEMORY_AREA));
362 Split->BaseAddress = BaseAddress + Length;
363 Split->Length = OriginalMemoryArea->Length - (((ULONG)BaseAddress)
364 + Length);
365
366 OriginalMemoryArea->Length = BaseAddress - OriginalMemoryArea->BaseAddress;
367
368 return(Split);
369 }
370
371 NTSTATUS MmCreateMemoryArea(PEPROCESS Process,
372 PMADDRESS_SPACE AddressSpace,
373 ULONG Type,
374 PVOID* BaseAddress,
375 ULONG Length,
376 ULONG Attributes,
377 MEMORY_AREA** Result)
378 /*
379 * FUNCTION: Create a memory area
380 * ARGUMENTS:
381 * AddressSpace = Address space to create the area in
382 * Type = Type of the address space
383 * BaseAddress =
384 * Length = Length to allocate
385 * Attributes = Protection attributes for the memory area
386 * Result = Receives a pointer to the memory area on exit
387 * RETURNS: Status
388 * NOTES: Lock the address space before calling this function
389 */
390 {
391 DPRINT("MmCreateMemoryArea(Type %d, BaseAddress %x,"
392 "*BaseAddress %x, Length %x, Attributes %x, Result %x)\n",
393 Type,BaseAddress,*BaseAddress,Length,Attributes,Result);
394
395 if ((*BaseAddress)==0)
396 {
397 *BaseAddress = MmFindGap(AddressSpace,
398 PAGE_ROUND_UP(Length) +(PAGESIZE*2));
399 if ((*BaseAddress)==0)
400 {
401 DPRINT("No suitable gap\n");
402 return(STATUS_UNSUCCESSFUL);
403 }
404 (*BaseAddress)=(*BaseAddress)+PAGESIZE;
405 }
406 else
407 {
408 (*BaseAddress) = (PVOID)PAGE_ROUND_DOWN((*BaseAddress));
409 if (MmOpenMemoryAreaByRegion(AddressSpace,
410 *BaseAddress,
411 Length)!=NULL)
412 {
413 DPRINT("Memory area already occupied\n");
414 return(STATUS_UNSUCCESSFUL);
415 }
416 }
417
418 *Result = ExAllocatePoolWithTag(NonPagedPool, sizeof(MEMORY_AREA),
419 TAG_MAREA);
420 RtlZeroMemory(*Result,sizeof(MEMORY_AREA));
421 (*Result)->Type = Type;
422 (*Result)->BaseAddress = *BaseAddress;
423 (*Result)->Length = Length;
424 (*Result)->Attributes = Attributes;
425 (*Result)->LockCount = 0;
426 (*Result)->Process = Process;
427
428 MmInsertMemoryArea(AddressSpace, *Result);
429
430 DPRINT("MmCreateMemoryArea() succeeded\n");
431 return(STATUS_SUCCESS);
432 }