5765d92fedc9cb1f43d7d7145d2fdd78bdc6b4dd
[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 MMPFNLIST MmZeroedPageListHead;
22 MMPFNLIST MmFreePageListHead;
23 MMPFNLIST MmStandbyPageListHead;
24 MMPFNLIST MmModifiedPageListHead;
25 MMPFNLIST MmModifiedNoWritePageListHead;
26
27 /* FUNCTIONS ******************************************************************/
28
29 VOID
30 NTAPI
31 MiInsertInListTail(IN PMMPFNLIST ListHead,
32 IN PMMPFN Entry)
33 {
34 PFN_NUMBER OldBlink, EntryIndex = MiGetPfnEntryIndex(Entry);
35
36 /* Get the back link */
37 OldBlink = ListHead->Blink;
38 if (OldBlink != LIST_HEAD)
39 {
40 /* Set the back pointer to point to us now */
41 MiGetPfnEntry(OldBlink)->u1.Flink = EntryIndex;
42 }
43 else
44 {
45 /* Set the list to point to us */
46 ListHead->Flink = EntryIndex;
47 }
48
49 /* Set the entry to point to the list head forwards, and the old page backwards */
50 Entry->u1.Flink = LIST_HEAD;
51 Entry->u2.Blink = OldBlink;
52
53 /* And now the head points back to us, since we are last */
54 ListHead->Blink = EntryIndex;
55 ListHead->Total++;
56 }
57
58 VOID
59 NTAPI
60 MiRemoveFromList(IN PMMPFN Entry)
61 {
62 PFN_NUMBER OldFlink, OldBlink;
63 PMMPFNLIST ListHead;
64
65 /* Find the list for this */
66 if (Entry->u3.e1.PageLocation == ZeroedPageList)
67 {
68 ListHead = &MmZeroedPageListHead;
69 }
70 else if (Entry->u3.e1.PageLocation == FreePageList)
71 {
72 ListHead = &MmFreePageListHead;
73 }
74 else
75 {
76 ListHead = NULL;
77 ASSERT(ListHead != NULL);
78 }
79
80 /* Get the forward and back pointers */
81 OldFlink = Entry->u1.Flink;
82 OldBlink = Entry->u2.Blink;
83
84 /* Check if the next entry is the list head */
85 if (OldFlink != LIST_HEAD)
86 {
87 /* It is not, so set the backlink of the actual entry, to our backlink */
88 MiGetPfnEntry(OldFlink)->u2.Blink = OldBlink;
89 }
90 else
91 {
92 /* Set the list head's backlink instead */
93 ListHead->Blink = OldFlink;
94 }
95
96 /* Check if the back entry is the list head */
97 if (OldBlink != LIST_HEAD)
98 {
99 /* It is not, so set the backlink of the actual entry, to our backlink */
100 MiGetPfnEntry(OldBlink)->u1.Flink = OldFlink;
101 }
102 else
103 {
104 /* Set the list head's backlink instead */
105 ListHead->Flink = OldFlink;
106 }
107
108 /* We are not on a list anymore */
109 ListHead->Total--;
110 Entry->u1.Flink = Entry->u2.Blink = 0;
111 }
112
113 PMMPFN
114 NTAPI
115 MiRemoveHeadList(IN PMMPFNLIST ListHead)
116 {
117 PFN_NUMBER Entry, Flink;
118 PMMPFN Pfn1;
119
120 /* Get the entry that's currently first on the list */
121 Entry = ListHead->Flink;
122 Pfn1 = MiGetPfnEntry(Entry);
123
124 /* Make the list point to the entry following the first one */
125 Flink = Pfn1->u1.Flink;
126 ListHead->Flink = Flink;
127
128 /* Check if the next entry is actually the list head */
129 if (ListHead->Flink != LIST_HEAD)
130 {
131 /* It isn't, so therefore whoever is coming next points back to the head */
132 MiGetPfnEntry(Flink)->u2.Blink = LIST_HEAD;
133 }
134 else
135 {
136 /* Then the list is empty, so the backlink should point back to us */
137 ListHead->Blink = LIST_HEAD;
138 }
139
140 /* We are not on a list anymore */
141 Pfn1->u1.Flink = Pfn1->u2.Blink = 0;
142 ListHead->Total--;
143
144 /* Return the head element */
145 return Pfn1;
146 }
147
148 VOID
149 NTAPI
150 MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex)
151 {
152 MMLISTS ListName;
153 PMMPFNLIST ListHead;
154 PFN_NUMBER LastPage;
155 PMMPFN Pfn1, Blink;
156 ULONG Color;
157 PMMCOLOR_TABLES ColorHead;
158
159 /* Make sure the page index is valid */
160 ASSERT((PageFrameIndex != 0) &&
161 (PageFrameIndex <= MmHighestPhysicalPage) &&
162 (PageFrameIndex >= MmLowestPhysicalPage));
163
164 /* Get the PFN entry */
165 Pfn1 = MI_PFN_TO_PFNENTRY(PageFrameIndex);
166
167 /* Sanity checks that a right kind of page is being inserted here */
168 ASSERT(Pfn1->u4.MustBeCached == 0);
169 ASSERT(Pfn1->u3.e1.Rom != 1);
170 ASSERT(Pfn1->u3.e1.RemovalRequested == 0);
171 ASSERT(Pfn1->u4.VerifierAllocation == 0);
172 ASSERT(Pfn1->u3.e2.ReferenceCount == 0);
173
174 /* Get the free page list and increment its count */
175 ListHead = &MmFreePageListHead;
176 ListName = FreePageList;
177 ListHead->Total++;
178
179 /* Get the last page on the list */
180 LastPage = ListHead->Blink;
181 if (LastPage != -1)
182 {
183 /* Link us with the previous page, so we're at the end now */
184 MI_PFN_TO_PFNENTRY(LastPage)->u1.Flink = PageFrameIndex;
185 }
186 else
187 {
188 /* The list is empty, so we are the first page */
189 ListHead->Flink = PageFrameIndex;
190 }
191
192 /* Now make the list head point back to us (since we go at the end) */
193 ListHead->Blink = PageFrameIndex;
194
195 /* And initialize our own list pointers */
196 Pfn1->u1.Flink = -1;
197 Pfn1->u2.Blink = LastPage;
198
199 /* Set the list name and default priority */
200 Pfn1->u3.e1.PageLocation = ListName;
201 Pfn1->u4.Priority = 3;
202
203 /* Clear some status fields */
204 Pfn1->u4.InPageError = 0;
205 Pfn1->u4.AweAllocation = 0;
206
207 /* FIXME: More work to be done regarding page accounting */
208
209 /* Get the page color */
210 Color = PageFrameIndex & MmSecondaryColorMask;
211
212 /* Get the first page on the color list */
213 ColorHead = &MmFreePagesByColor[ListName][Color];
214 if (ColorHead->Flink == -1)
215 {
216 /* The list is empty, so we are the first page */
217 Pfn1->u4.PteFrame = -1;
218 ColorHead->Flink = PageFrameIndex;
219 }
220 else
221 {
222 /* Get the previous page */
223 Blink = (PMMPFN)ColorHead->Blink;
224
225 /* Make it link to us */
226 Pfn1->u4.PteFrame = MI_PFNENTRY_TO_PFN(Blink);
227 Blink->OriginalPte.u.Long = PageFrameIndex;
228 }
229
230 /* Now initialize our own list pointers */
231 ColorHead->Blink = Pfn1;
232 Pfn1->OriginalPte.u.Long = -1;
233
234 /* And increase the count in the colored list */
235 ColorHead->Count++;
236
237 /* FIXME: Notify zero page thread if enough pages are on the free list now */
238 }
239
240 /* EOF */