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