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
9 /* INCLUDES *******************************************************************/
15 #line 15 "ARMĀ³::PFNLIST"
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "../ARM3/miarm.h"
19 /* GLOBALS ********************************************************************/
21 MMPFNLIST MmZeroedPageListHead
;
22 MMPFNLIST MmFreePageListHead
;
23 MMPFNLIST MmStandbyPageListHead
;
24 MMPFNLIST MmModifiedPageListHead
;
25 MMPFNLIST MmModifiedNoWritePageListHead
;
27 /* FUNCTIONS ******************************************************************/
31 MiInsertInListTail(IN PMMPFNLIST ListHead
,
34 PFN_NUMBER OldBlink
, EntryIndex
= MiGetPfnEntryIndex(Entry
);
36 /* Get the back link */
37 OldBlink
= ListHead
->Blink
;
38 if (OldBlink
!= LIST_HEAD
)
40 /* Set the back pointer to point to us now */
41 MiGetPfnEntry(OldBlink
)->u1
.Flink
= EntryIndex
;
45 /* Set the list to point to us */
46 ListHead
->Flink
= EntryIndex
;
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
;
53 /* And now the head points back to us, since we are last */
54 ListHead
->Blink
= EntryIndex
;
60 MiRemoveFromList(IN PMMPFN Entry
)
62 PFN_NUMBER OldFlink
, OldBlink
;
65 /* Find the list for this */
66 if (Entry
->u3
.e1
.PageLocation
== ZeroedPageList
)
68 ListHead
= &MmZeroedPageListHead
;
70 else if (Entry
->u3
.e1
.PageLocation
== FreePageList
)
72 ListHead
= &MmFreePageListHead
;
77 ASSERT(ListHead
!= NULL
);
80 /* Get the forward and back pointers */
81 OldFlink
= Entry
->u1
.Flink
;
82 OldBlink
= Entry
->u2
.Blink
;
84 /* Check if the next entry is the list head */
85 if (OldFlink
!= LIST_HEAD
)
87 /* It is not, so set the backlink of the actual entry, to our backlink */
88 MiGetPfnEntry(OldFlink
)->u2
.Blink
= OldBlink
;
92 /* Set the list head's backlink instead */
93 ListHead
->Blink
= OldFlink
;
96 /* Check if the back entry is the list head */
97 if (OldBlink
!= LIST_HEAD
)
99 /* It is not, so set the backlink of the actual entry, to our backlink */
100 MiGetPfnEntry(OldBlink
)->u1
.Flink
= OldFlink
;
104 /* Set the list head's backlink instead */
105 ListHead
->Flink
= OldFlink
;
108 /* We are not on a list anymore */
110 Entry
->u1
.Flink
= Entry
->u2
.Blink
= 0;
115 MiRemoveHeadList(IN PMMPFNLIST ListHead
)
117 PFN_NUMBER Entry
, Flink
;
120 /* Get the entry that's currently first on the list */
121 Entry
= ListHead
->Flink
;
122 Pfn1
= MiGetPfnEntry(Entry
);
124 /* Make the list point to the entry following the first one */
125 Flink
= Pfn1
->u1
.Flink
;
126 ListHead
->Flink
= Flink
;
128 /* Check if the next entry is actually the list head */
129 if (ListHead
->Flink
!= LIST_HEAD
)
131 /* It isn't, so therefore whoever is coming next points back to the head */
132 MiGetPfnEntry(Flink
)->u2
.Blink
= LIST_HEAD
;
136 /* Then the list is empty, so the backlink should point back to us */
137 ListHead
->Blink
= LIST_HEAD
;
140 /* We are not on a list anymore */
141 Pfn1
->u1
.Flink
= Pfn1
->u2
.Blink
= 0;
144 /* Return the head element */
150 MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex
)
157 PMMCOLOR_TABLES ColorHead
;
159 /* Make sure the page index is valid */
160 ASSERT((PageFrameIndex
!= 0) &&
161 (PageFrameIndex
<= MmHighestPhysicalPage
) &&
162 (PageFrameIndex
>= MmLowestPhysicalPage
));
164 /* Get the PFN entry */
165 Pfn1
= MI_PFN_TO_PFNENTRY(PageFrameIndex
);
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);
174 /* Get the free page list and increment its count */
175 ListHead
= &MmFreePageListHead
;
176 ListName
= FreePageList
;
179 /* Get the last page on the list */
180 LastPage
= ListHead
->Blink
;
183 /* Link us with the previous page, so we're at the end now */
184 MI_PFN_TO_PFNENTRY(LastPage
)->u1
.Flink
= PageFrameIndex
;
188 /* The list is empty, so we are the first page */
189 ListHead
->Flink
= PageFrameIndex
;
192 /* Now make the list head point back to us (since we go at the end) */
193 ListHead
->Blink
= PageFrameIndex
;
195 /* And initialize our own list pointers */
197 Pfn1
->u2
.Blink
= LastPage
;
199 /* Set the list name and default priority */
200 Pfn1
->u3
.e1
.PageLocation
= ListName
;
201 Pfn1
->u4
.Priority
= 3;
203 /* Clear some status fields */
204 Pfn1
->u4
.InPageError
= 0;
205 Pfn1
->u4
.AweAllocation
= 0;
207 /* FIXME: More work to be done regarding page accounting */
209 /* Get the page color */
210 Color
= PageFrameIndex
& MmSecondaryColorMask
;
212 /* Get the first page on the color list */
213 ColorHead
= &MmFreePagesByColor
[ListName
][Color
];
214 if (ColorHead
->Flink
== -1)
216 /* The list is empty, so we are the first page */
217 Pfn1
->u4
.PteFrame
= -1;
218 ColorHead
->Flink
= PageFrameIndex
;
222 /* Get the previous page */
223 Blink
= (PMMPFN
)ColorHead
->Blink
;
225 /* Make it link to us */
226 Pfn1
->u4
.PteFrame
= MI_PFNENTRY_TO_PFN(Blink
);
227 Blink
->OriginalPte
.u
.Long
= PageFrameIndex
;
230 /* Now initialize our own list pointers */
231 ColorHead
->Blink
= Pfn1
;
232 Pfn1
->OriginalPte
.u
.Long
= -1;
234 /* And increase the count in the colored list */
237 /* FIXME: Notify zero page thread if enough pages are on the free list now */