[NTOS]: Read almost all the Memory Management variables into the system configuration...
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / pfnlist.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/pfnlist.c
5 * PURPOSE: ARM Memory Manager PFN List Manipulation
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 #line 15 "ARMĀ³::PFNLIST"
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "../ARM3/miarm.h"
18
19 /* GLOBALS ********************************************************************/
20
21 BOOLEAN MmDynamicPfn;
22 BOOLEAN MmMirroring;
23
24 MMPFNLIST MmZeroedPageListHead = {0, ZeroedPageList, LIST_HEAD, LIST_HEAD};
25 MMPFNLIST MmFreePageListHead = {0, FreePageList, LIST_HEAD, LIST_HEAD};
26 MMPFNLIST MmStandbyPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD};
27 MMPFNLIST MmModifiedPageListHead = {0, ModifiedPageList, LIST_HEAD, LIST_HEAD};
28 MMPFNLIST MmModifiedNoWritePageListHead = {0, ModifiedNoWritePageList, LIST_HEAD, LIST_HEAD};
29 MMPFNLIST MmBadPageListHead = {0, BadPageList, LIST_HEAD, LIST_HEAD};
30 MMPFNLIST MmRomPageListHead = {0, StandbyPageList, LIST_HEAD, LIST_HEAD};
31
32 PMMPFNLIST MmPageLocationList[] =
33 {
34 &MmZeroedPageListHead,
35 &MmFreePageListHead,
36 &MmStandbyPageListHead,
37 &MmModifiedPageListHead,
38 &MmModifiedNoWritePageListHead,
39 &MmBadPageListHead,
40 NULL,
41 NULL
42 };
43 /* FUNCTIONS ******************************************************************/
44
45 VOID
46 NTAPI
47 MiInsertInListTail(IN PMMPFNLIST ListHead,
48 IN PMMPFN Entry)
49 {
50 PFN_NUMBER OldBlink, EntryIndex = MiGetPfnEntryIndex(Entry);
51
52 /* Get the back link */
53 OldBlink = ListHead->Blink;
54 if (OldBlink != LIST_HEAD)
55 {
56 /* Set the back pointer to point to us now */
57 MiGetPfnEntry(OldBlink)->u1.Flink = EntryIndex;
58 }
59 else
60 {
61 /* Set the list to point to us */
62 ListHead->Flink = EntryIndex;
63 }
64
65 /* Set the entry to point to the list head forwards, and the old page backwards */
66 Entry->u1.Flink = LIST_HEAD;
67 Entry->u2.Blink = OldBlink;
68
69 /* And now the head points back to us, since we are last */
70 ListHead->Blink = EntryIndex;
71 ListHead->Total++;
72 }
73
74 VOID
75 NTAPI
76 MiInsertZeroListAtBack(IN PFN_NUMBER EntryIndex)
77 {
78 PFN_NUMBER OldBlink;
79 PMMPFNLIST ListHead;
80 PMMPFN Pfn1;
81 #if 0
82 PMMPFN Blink;
83 ULONG Color;
84 PMMCOLOR_TABLES ColorHead;
85 #endif
86
87 /* Make sure the PFN lock is held */
88 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
89
90 /* Get the descriptor */
91 Pfn1 = MiGetPfnEntry(EntryIndex);
92 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
93 ASSERT(Pfn1->u4.MustBeCached == 0);
94 ASSERT(Pfn1->u3.e1.Rom == 0);
95 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
96 ASSERT(Pfn1->u4.InPageError == 0);
97
98 /* Use the zero list */
99 ListHead = &MmZeroedPageListHead;
100 ListHead->Total++;
101
102 /* Get the back link */
103 OldBlink = ListHead->Blink;
104 if (OldBlink != LIST_HEAD)
105 {
106 /* Set the back pointer to point to us now */
107 MiGetPfnEntry(OldBlink)->u1.Flink = EntryIndex;
108 }
109 else
110 {
111 /* Set the list to point to us */
112 ListHead->Flink = EntryIndex;
113 }
114
115 /* Set the entry to point to the list head forwards, and the old page backwards */
116 Pfn1->u1.Flink = LIST_HEAD;
117 Pfn1->u2.Blink = OldBlink;
118
119 /* And now the head points back to us, since we are last */
120 ListHead->Blink = EntryIndex;
121
122 /* Update the page location */
123 Pfn1->u3.e1.PageLocation = ZeroedPageList;
124
125 /* FIXME: NOT YET Due to caller semantics: Update the available page count */
126 //MmAvailablePages++;
127
128 /* Check if we've reached the configured low memory threshold */
129 if (MmAvailablePages == MmLowMemoryThreshold)
130 {
131 /* Clear the event, because now we're ABOVE the threshold */
132 KeClearEvent(MiLowMemoryEvent);
133 }
134 else if (MmAvailablePages == MmHighMemoryThreshold)
135 {
136 /* Otherwise check if we reached the high threshold and signal the event */
137 KeSetEvent(MiHighMemoryEvent, 0, FALSE);
138 }
139 #if 0
140 /* Get the page color */
141 Color = EntryIndex & MmSecondaryColorMask;
142
143 /* Get the first page on the color list */
144 ColorHead = &MmFreePagesByColor[ZeroedPageList][Color];
145 if (ColorHead->Flink == LIST_HEAD)
146 {
147 /* The list is empty, so we are the first page */
148 Pfn1->u4.PteFrame = -1;
149 ColorHead->Flink = EntryIndex;
150 }
151 else
152 {
153 /* Get the previous page */
154 Blink = (PMMPFN)ColorHead->Blink;
155
156 /* Make it link to us */
157 Pfn1->u4.PteFrame = MiGetPfnEntryIndex(Blink);
158 Blink->OriginalPte.u.Long = EntryIndex;
159 }
160
161 /* Now initialize our own list pointers */
162 ColorHead->Blink = Pfn1;
163 Pfn1->OriginalPte.u.Long = LIST_HEAD;
164
165 /* And increase the count in the colored list */
166 ColorHead->Count++;
167 #endif
168 }
169
170 VOID
171 NTAPI
172 MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry)
173 {
174 PFN_NUMBER OldFlink, OldBlink;
175 PMMPFNLIST ListHead;
176 MMLISTS ListName;
177
178 /* Make sure the PFN lock is held */
179 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
180
181 /* Make sure the PFN entry isn't in-use */
182 ASSERT(Entry->u3.e1.WriteInProgress == 0);
183 ASSERT(Entry->u3.e1.ReadInProgress == 0);
184
185 /* Find the list for this entry, make sure it's the free or zero list */
186 ListHead = MmPageLocationList[Entry->u3.e1.PageLocation];
187 ListName = ListHead->ListName;
188 ASSERT(ListHead != NULL);
189 ASSERT(ListName <= FreePageList);
190
191 /* Remove one count */
192 ASSERT(ListHead->Total != 0);
193 ListHead->Total--;
194
195 /* Get the forward and back pointers */
196 OldFlink = Entry->u1.Flink;
197 OldBlink = Entry->u2.Blink;
198
199 /* Check if the next entry is the list head */
200 if (OldFlink != LIST_HEAD)
201 {
202 /* It is not, so set the backlink of the actual entry, to our backlink */
203 MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink;
204 }
205 else
206 {
207 /* Set the list head's backlink instead */
208 ListHead->Blink = OldFlink;
209 }
210
211 /* Check if the back entry is the list head */
212 if (OldBlink != LIST_HEAD)
213 {
214 /* It is not, so set the backlink of the actual entry, to our backlink */
215 MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink;
216 }
217 else
218 {
219 /* Set the list head's backlink instead */
220 ListHead->Flink = OldFlink;
221 }
222
223 /* We are not on a list anymore */
224 Entry->u1.Flink = Entry->u2.Blink = 0;
225
226 /* FIXME: Deal with color list */
227
228 /* See if we hit any thresholds */
229 if (MmAvailablePages == MmHighMemoryThreshold)
230 {
231 /* Clear the high memory event */
232 KeClearEvent(MiHighMemoryEvent);
233 }
234 else if (MmAvailablePages == MmLowMemoryThreshold)
235 {
236 /* Signal the low memory event */
237 KeSetEvent(MiLowMemoryEvent, 0, FALSE);
238 }
239
240 /* One less page */
241 if (--MmAvailablePages < MmMinimumFreePages)
242 {
243 /* FIXME: Should wake up the MPW and working set manager, if we had one */
244 }
245 }
246
247 PMMPFN
248 NTAPI
249 MiRemoveHeadList(IN PMMPFNLIST ListHead)
250 {
251 PFN_NUMBER Entry, Flink;
252 PMMPFN Pfn1;
253
254 /* Get the entry that's currently first on the list */
255 Entry = ListHead->Flink;
256 Pfn1 = MiGetPfnEntry(Entry);
257
258 /* Make the list point to the entry following the first one */
259 Flink = Pfn1->u1.Flink;
260 ListHead->Flink = Flink;
261
262 /* Check if the next entry is actually the list head */
263 if (ListHead->Flink != LIST_HEAD)
264 {
265 /* It isn't, so therefore whoever is coming next points back to the head */
266 MiGetPfnEntry(Flink)->u2.Blink = LIST_HEAD;
267 }
268 else
269 {
270 /* Then the list is empty, so the backlink should point back to us */
271 ListHead->Blink = LIST_HEAD;
272 }
273
274 /* We are not on a list anymore */
275 Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
276 ListHead->Total--;
277
278 /* Return the head element */
279 return Pfn1;
280 }
281
282 VOID
283 NTAPI
284 MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
285 {
286 PMMPFNLIST ListHead;
287 PFN_NUMBER LastPage;
288 PMMPFN Pfn1, Blink;
289 ULONG Color;
290 PMMCOLOR_TABLES ColorHead;
291
292 /* Make sure the page index is valid */
293 ASSERT((PageFrameIndex != 0) &&
294 (PageFrameIndex <= MmHighestPhysicalPage) &&
295 (PageFrameIndex >= MmLowestPhysicalPage));
296
297 /* Get the PFN entry */
298 Pfn1 = MI_PFN_TO_PFNENTRY(PageFrameIndex);
299
300 /* Sanity checks that a right kind of page is being inserted here */
301 ASSERT(Pfn1->u4.MustBeCached == 0);
302 ASSERT(Pfn1->u3.e1.Rom != 1);
303 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
304 ASSERT(Pfn1->u4.VerifierAllocation == 0);
305 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
306
307 /* Get the free page list and increment its count */
308 ListHead = &MmFreePageListHead;
309 ListHead->Total++;
310
311 /* Get the last page on the list */
312 LastPage = ListHead->Blink;
313 if (LastPage != LIST_HEAD)
314 {
315 /* Link us with the previous page, so we're at the end now */
316 MI_PFN_TO_PFNENTRY(LastPage)->u1.Flink = PageFrameIndex;
317 }
318 else
319 {
320 /* The list is empty, so we are the first page */
321 ListHead->Flink = PageFrameIndex;
322 }
323
324 /* Now make the list head point back to us (since we go at the end) */
325 ListHead->Blink = PageFrameIndex;
326
327 /* And initialize our own list pointers */
328 Pfn1->u1.Flink = LIST_HEAD;
329 Pfn1->u2.Blink = LastPage;
330
331 /* Set the list name and default priority */
332 Pfn1->u3.e1.PageLocation = FreePageList;
333 Pfn1->u4.Priority = 3;
334
335 /* Clear some status fields */
336 Pfn1->u4.InPageError = 0;
337 Pfn1->u4.AweAllocation = 0;
338
339 /* Not yet until we switch to this */
340 //MmAvailablePages++;
341
342 /* Check if we've reached the configured low memory threshold */
343 if (MmAvailablePages == MmLowMemoryThreshold)
344 {
345 /* Clear the event, because now we're ABOVE the threshold */
346 KeClearEvent(MiLowMemoryEvent);
347 }
348 else if (MmAvailablePages == MmHighMemoryThreshold)
349 {
350 /* Otherwise check if we reached the high threshold and signal the event */
351 KeSetEvent(MiHighMemoryEvent, 0, FALSE);
352 }
353
354 /* Get the page color */
355 Color = PageFrameIndex & MmSecondaryColorMask;
356
357 /* Get the first page on the color list */
358 ColorHead = &MmFreePagesByColor[FreePageList][Color];
359 if (ColorHead->Flink == LIST_HEAD)
360 {
361 /* The list is empty, so we are the first page */
362 Pfn1->u4.PteFrame = -1;
363 ColorHead->Flink = PageFrameIndex;
364 }
365 else
366 {
367 /* Get the previous page */
368 Blink = (PMMPFN)ColorHead->Blink;
369
370 /* Make it link to us */
371 Pfn1->u4.PteFrame = MI_PFNENTRY_TO_PFN(Blink);
372 Blink->OriginalPte.u.Long = PageFrameIndex;
373 }
374
375 /* Now initialize our own list pointers */
376 ColorHead->Blink = Pfn1;
377 Pfn1->OriginalPte.u.Long = LIST_HEAD;
378
379 /* And increase the count in the colored list */
380 ColorHead->Count++;
381
382 /* FIXME: Notify zero page thread if enough pages are on the free list now */
383 }
384
385 /* EOF */