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"
20 #define ASSERT_LIST_INVARIANT(x) \
22 ASSERT(((x)->Total == 0 && \
23 (x)->Flink == LIST_HEAD && \
24 (x)->Blink == LIST_HEAD) || \
26 (x)->Flink != LIST_HEAD && \
27 (x)->Blink != LIST_HEAD)); \
30 #define ASSERT_LIST_INVARIANT(x)
33 /* GLOBALS ********************************************************************/
38 MMPFNLIST MmZeroedPageListHead
= {0, ZeroedPageList
, LIST_HEAD
, LIST_HEAD
};
39 MMPFNLIST MmFreePageListHead
= {0, FreePageList
, LIST_HEAD
, LIST_HEAD
};
40 MMPFNLIST MmStandbyPageListHead
= {0, StandbyPageList
, LIST_HEAD
, LIST_HEAD
};
41 MMPFNLIST MmModifiedPageListHead
= {0, ModifiedPageList
, LIST_HEAD
, LIST_HEAD
};
42 MMPFNLIST MmModifiedNoWritePageListHead
= {0, ModifiedNoWritePageList
, LIST_HEAD
, LIST_HEAD
};
43 MMPFNLIST MmBadPageListHead
= {0, BadPageList
, LIST_HEAD
, LIST_HEAD
};
44 MMPFNLIST MmRomPageListHead
= {0, StandbyPageList
, LIST_HEAD
, LIST_HEAD
};
46 PMMPFNLIST MmPageLocationList
[] =
48 &MmZeroedPageListHead
,
50 &MmStandbyPageListHead
,
51 &MmModifiedPageListHead
,
52 &MmModifiedNoWritePageListHead
,
57 /* FUNCTIONS ******************************************************************/
61 MiInsertInListTail(IN PMMPFNLIST ListHead
,
64 PFN_NUMBER OldBlink
, EntryIndex
= MiGetPfnEntryIndex(Entry
);
65 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
66 ASSERT_LIST_INVARIANT(ListHead
);
68 /* Get the back link */
69 OldBlink
= ListHead
->Blink
;
70 if (OldBlink
!= LIST_HEAD
)
72 /* Set the back pointer to point to us now */
73 MiGetPfnEntry(OldBlink
)->u1
.Flink
= EntryIndex
;
77 /* Set the list to point to us */
78 ListHead
->Flink
= EntryIndex
;
81 /* Set the entry to point to the list head forwards, and the old page backwards */
82 Entry
->u1
.Flink
= LIST_HEAD
;
83 Entry
->u2
.Blink
= OldBlink
;
85 /* And now the head points back to us, since we are last */
86 ListHead
->Blink
= EntryIndex
;
88 ASSERT_LIST_INVARIANT(ListHead
);
93 MiInsertZeroListAtBack(IN PFN_NUMBER EntryIndex
)
101 PMMCOLOR_TABLES ColorHead
;
104 /* Make sure the PFN lock is held */
105 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
107 /* Get the descriptor */
108 Pfn1
= MiGetPfnEntry(EntryIndex
);
109 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
== 0);
110 ASSERT(Pfn1
->u4
.MustBeCached
== 0);
111 ASSERT(Pfn1
->u3
.e1
.Rom
== 0);
112 ASSERT(Pfn1
->u3
.e1
.RemovalRequested
== 0);
113 ASSERT(Pfn1
->u4
.InPageError
== 0);
115 /* Use the zero list */
116 ListHead
= &MmZeroedPageListHead
;
117 ASSERT_LIST_INVARIANT(ListHead
);
120 /* Get the back link */
121 OldBlink
= ListHead
->Blink
;
122 if (OldBlink
!= LIST_HEAD
)
124 /* Set the back pointer to point to us now */
125 MiGetPfnEntry(OldBlink
)->u1
.Flink
= EntryIndex
;
129 /* Set the list to point to us */
130 ListHead
->Flink
= EntryIndex
;
133 /* Set the entry to point to the list head forwards, and the old page backwards */
134 Pfn1
->u1
.Flink
= LIST_HEAD
;
135 Pfn1
->u2
.Blink
= OldBlink
;
137 /* And now the head points back to us, since we are last */
138 ListHead
->Blink
= EntryIndex
;
139 ASSERT_LIST_INVARIANT(ListHead
);
141 /* Update the page location */
142 Pfn1
->u3
.e1
.PageLocation
= ZeroedPageList
;
144 /* FIXME: NOT YET Due to caller semantics: Update the available page count */
145 //MmAvailablePages++;
147 /* Check if we've reached the configured low memory threshold */
148 if (MmAvailablePages
== MmLowMemoryThreshold
)
150 /* Clear the event, because now we're ABOVE the threshold */
151 KeClearEvent(MiLowMemoryEvent
);
153 else if (MmAvailablePages
== MmHighMemoryThreshold
)
155 /* Otherwise check if we reached the high threshold and signal the event */
156 KeSetEvent(MiHighMemoryEvent
, 0, FALSE
);
160 /* Get the page color */
161 Color
= EntryIndex
& MmSecondaryColorMask
;
163 /* Get the first page on the color list */
164 ColorHead
= &MmFreePagesByColor
[ZeroedPageList
][Color
];
165 if (ColorHead
->Flink
== LIST_HEAD
)
167 /* The list is empty, so we are the first page */
168 Pfn1
->u4
.PteFrame
= -1;
169 ColorHead
->Flink
= EntryIndex
;
173 /* Get the previous page */
174 Blink
= (PMMPFN
)ColorHead
->Blink
;
176 /* Make it link to us */
177 Pfn1
->u4
.PteFrame
= MiGetPfnEntryIndex(Blink
);
178 Blink
->OriginalPte
.u
.Long
= EntryIndex
;
181 /* Now initialize our own list pointers */
182 ColorHead
->Blink
= Pfn1
;
183 Pfn1
->OriginalPte
.u
.Long
= LIST_HEAD
;
185 /* And increase the count in the colored list */
192 MiUnlinkFreeOrZeroedPage(IN PMMPFN Entry
)
194 PFN_NUMBER OldFlink
, OldBlink
;
198 /* Make sure the PFN lock is held */
199 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
201 /* Make sure the PFN entry isn't in-use */
202 ASSERT(Entry
->u3
.e1
.WriteInProgress
== 0);
203 ASSERT(Entry
->u3
.e1
.ReadInProgress
== 0);
205 /* Find the list for this entry, make sure it's the free or zero list */
206 ListHead
= MmPageLocationList
[Entry
->u3
.e1
.PageLocation
];
207 ListName
= ListHead
->ListName
;
208 ASSERT(ListHead
!= NULL
);
209 ASSERT(ListName
<= FreePageList
);
210 ASSERT_LIST_INVARIANT(ListHead
);
212 /* Remove one count */
213 ASSERT(ListHead
->Total
!= 0);
216 /* Get the forward and back pointers */
217 OldFlink
= Entry
->u1
.Flink
;
218 OldBlink
= Entry
->u2
.Blink
;
220 /* Check if the next entry is the list head */
221 if (OldFlink
!= LIST_HEAD
)
223 /* It is not, so set the backlink of the actual entry, to our backlink */
224 MiGetPfnEntry(OldFlink
)->u2
.Blink
= OldBlink
;
228 /* Set the list head's backlink instead */
229 ListHead
->Blink
= OldBlink
;
232 /* Check if the back entry is the list head */
233 if (OldBlink
!= LIST_HEAD
)
235 /* It is not, so set the backlink of the actual entry, to our backlink */
236 MiGetPfnEntry(OldBlink
)->u1
.Flink
= OldFlink
;
240 /* Set the list head's backlink instead */
241 ListHead
->Flink
= OldFlink
;
244 /* We are not on a list anymore */
245 Entry
->u1
.Flink
= Entry
->u2
.Blink
= 0;
246 ASSERT_LIST_INVARIANT(ListHead
);
248 /* FIXME: Deal with color list */
250 /* See if we hit any thresholds */
251 if (MmAvailablePages
== MmHighMemoryThreshold
)
253 /* Clear the high memory event */
254 KeClearEvent(MiHighMemoryEvent
);
256 else if (MmAvailablePages
== MmLowMemoryThreshold
)
258 /* Signal the low memory event */
259 KeSetEvent(MiLowMemoryEvent
, 0, FALSE
);
263 if (--MmAvailablePages
< MmMinimumFreePages
)
265 /* FIXME: Should wake up the MPW and working set manager, if we had one */
271 MiRemovePageByColor(IN PFN_NUMBER PageIndex
,
277 PFN_NUMBER OldFlink
, OldBlink
;
278 ULONG OldColor
, OldCache
;
280 PMMCOLOR_TABLES ColorTable
;
282 /* Make sure PFN lock is held */
283 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
284 ASSERT(Color
< MmSecondaryColors
);
286 /* Get the PFN entry */
287 Pfn1
= MiGetPfnEntry(PageIndex
);
288 ASSERT(Pfn1
->u3
.e1
.RemovalRequested
== 0);
289 ASSERT(Pfn1
->u3
.e1
.Rom
== 0);
291 /* Capture data for later */
292 OldColor
= Pfn1
->u3
.e1
.PageColor
;
293 OldCache
= Pfn1
->u3
.e1
.CacheAttribute
;
295 /* Could be either on free or zero list */
296 ListHead
= MmPageLocationList
[Pfn1
->u3
.e1
.PageLocation
];
297 ASSERT_LIST_INVARIANT(ListHead
);
298 ListName
= ListHead
->ListName
;
299 ASSERT(ListName
<= FreePageList
);
304 /* Get the forward and back pointers */
305 OldFlink
= Pfn1
->u1
.Flink
;
306 OldBlink
= Pfn1
->u2
.Blink
;
308 /* Check if the next entry is the list head */
309 if (OldFlink
!= LIST_HEAD
)
311 /* It is not, so set the backlink of the actual entry, to our backlink */
312 MiGetPfnEntry(OldFlink
)->u2
.Blink
= OldBlink
;
316 /* Set the list head's backlink instead */
317 ListHead
->Blink
= OldFlink
;
320 /* Check if the back entry is the list head */
321 if (OldBlink
!= LIST_HEAD
)
323 /* It is not, so set the backlink of the actual entry, to our backlink */
324 MiGetPfnEntry(OldBlink
)->u1
.Flink
= OldFlink
;
328 /* Set the list head's backlink instead */
329 ListHead
->Flink
= OldFlink
;
332 /* We are not on a list anymore */
333 ASSERT_LIST_INVARIANT(ListHead
);
334 Pfn1
->u1
.Flink
= Pfn1
->u2
.Blink
= 0;
336 /* Zero flags but restore color and cache */
337 Pfn1
->u3
.e2
.ShortFlags
= 0;
338 Pfn1
->u3
.e1
.PageColor
= OldColor
;
339 Pfn1
->u3
.e1
.CacheAttribute
= OldCache
;
341 #if 0 // When switching to ARM3
342 /* Get the first page on the color list */
343 ColorTable
= &MmFreePagesByColor
[ListName
][Color
];
344 ASSERT(ColorTable
->Count
>= 1);
346 /* Set the forward link to whoever we were pointing to */
347 ColorTable
->Flink
= Pfn1
->OriginalPte
.u
.Long
;
348 if (ColorTable
->Flink
== LIST_HEAD
)
350 /* This is the beginning of the list, so set the sentinel value */
351 ColorTable
->Blink
= LIST_HEAD
;
355 /* The list is empty, so we are the first page */
356 MiGetPfnEntry(ColorTable
->Flink
)->u4
.PteFrame
= -1;
362 /* See if we hit any thresholds */
363 if (MmAvailablePages
== MmHighMemoryThreshold
)
365 /* Clear the high memory event */
366 KeClearEvent(MiHighMemoryEvent
);
368 else if (MmAvailablePages
== MmLowMemoryThreshold
)
370 /* Signal the low memory event */
371 KeSetEvent(MiLowMemoryEvent
, 0, FALSE
);
375 if (--MmAvailablePages
< MmMinimumFreePages
)
377 /* FIXME: Should wake up the MPW and working set manager, if we had one */
380 /* Return the page */
386 MiRemoveAnyPage(IN ULONG Color
)
388 PFN_NUMBER PageIndex
;
391 /* Make sure PFN lock is held and we have pages */
392 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
393 ASSERT(MmAvailablePages
!= 0);
394 ASSERT(Color
< MmSecondaryColors
);
396 /* Check the colored free list */
397 #if 0 // Enable when using ARM3 database */
398 PageIndex
= MmFreePagesByColor
[FreePageList
][Color
].Flink
;
399 if (PageIndex
== LIST_HEAD
)
401 /* Check the colored zero list */
402 PageIndex
= MmFreePagesByColor
[ZeroedPageList
][Color
].Flink
;
403 if (PageIndex
== LIST_HEAD
)
406 /* Check the free list */
407 ASSERT_LIST_INVARIANT(&MmFreePageListHead
);
408 PageIndex
= MmFreePageListHead
.Flink
;
409 Color
= PageIndex
& MmSecondaryColorMask
;
410 if (PageIndex
== LIST_HEAD
)
412 /* Check the zero list */
413 ASSERT_LIST_INVARIANT(&MmZeroedPageListHead
);
414 PageIndex
= MmZeroedPageListHead
.Flink
;
415 Color
= PageIndex
& MmSecondaryColorMask
;
416 ASSERT(PageIndex
!= LIST_HEAD
);
417 if (PageIndex
== LIST_HEAD
)
419 /* FIXME: Should check the standby list */
420 ASSERT(MmZeroedPageListHead
.Total
== 0);
423 #if 0 // Enable when using ARM3 database */
428 /* Remove the page from its list */
429 PageIndex
= MiRemovePageByColor(PageIndex
, Color
);
432 Pfn1
= MiGetPfnEntry(PageIndex
);
433 ASSERT((Pfn1
->u3
.e1
.PageLocation
== FreePageList
) ||
434 (Pfn1
->u3
.e1
.PageLocation
== ZeroedPageList
));
435 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
== 0);
436 ASSERT(Pfn1
->u2
.ShareCount
== 0);
437 ASSERT_LIST_INVARIANT(&MmFreePageListHead
);
438 ASSERT_LIST_INVARIANT(&MmZeroedPageListHead
);
440 /* Return the page */
446 MiRemoveHeadList(IN PMMPFNLIST ListHead
)
448 PFN_NUMBER Entry
, Flink
;
450 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
451 ASSERT_LIST_INVARIANT(ListHead
);
453 /* Get the entry that's currently first on the list */
454 Entry
= ListHead
->Flink
;
455 Pfn1
= MiGetPfnEntry(Entry
);
457 /* Make the list point to the entry following the first one */
458 Flink
= Pfn1
->u1
.Flink
;
459 ListHead
->Flink
= Flink
;
461 /* Check if the next entry is actually the list head */
462 if (ListHead
->Flink
!= LIST_HEAD
)
464 /* It isn't, so therefore whoever is coming next points back to the head */
465 MiGetPfnEntry(Flink
)->u2
.Blink
= LIST_HEAD
;
469 /* Then the list is empty, so the backlink should point back to us */
470 ListHead
->Blink
= LIST_HEAD
;
473 /* We are not on a list anymore */
474 Pfn1
->u1
.Flink
= Pfn1
->u2
.Blink
= 0;
476 ASSERT_LIST_INVARIANT(ListHead
);
478 /* Return the head element */
484 MiInsertPageInFreeList(IN PFN_NUMBER PageFrameIndex
)
492 PMMCOLOR_TABLES ColorTable
;
494 /* Make sure the page index is valid */
495 ASSERT(KeGetCurrentIrql() >= DISPATCH_LEVEL
);
496 ASSERT((PageFrameIndex
!= 0) &&
497 (PageFrameIndex
<= MmHighestPhysicalPage
) &&
498 (PageFrameIndex
>= MmLowestPhysicalPage
));
500 /* Get the PFN entry */
501 Pfn1
= MiGetPfnEntry(PageFrameIndex
);
503 /* Sanity checks that a right kind of page is being inserted here */
504 ASSERT(Pfn1
->u4
.MustBeCached
== 0);
505 ASSERT(Pfn1
->u3
.e1
.Rom
!= 1);
506 ASSERT(Pfn1
->u3
.e1
.RemovalRequested
== 0);
507 ASSERT(Pfn1
->u4
.VerifierAllocation
== 0);
508 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
== 0);
510 /* Get the free page list and increment its count */
511 ListHead
= &MmFreePageListHead
;
512 ASSERT_LIST_INVARIANT(ListHead
);
515 /* Get the last page on the list */
516 LastPage
= ListHead
->Blink
;
517 if (LastPage
!= LIST_HEAD
)
519 /* Link us with the previous page, so we're at the end now */
520 MiGetPfnEntry(LastPage
)->u1
.Flink
= PageFrameIndex
;
524 /* The list is empty, so we are the first page */
525 ListHead
->Flink
= PageFrameIndex
;
528 /* Now make the list head point back to us (since we go at the end) */
529 ListHead
->Blink
= PageFrameIndex
;
530 ASSERT_LIST_INVARIANT(ListHead
);
532 /* And initialize our own list pointers */
533 Pfn1
->u1
.Flink
= LIST_HEAD
;
534 Pfn1
->u2
.Blink
= LastPage
;
536 /* Set the list name and default priority */
537 Pfn1
->u3
.e1
.PageLocation
= FreePageList
;
538 Pfn1
->u4
.Priority
= 3;
540 /* Clear some status fields */
541 Pfn1
->u4
.InPageError
= 0;
542 Pfn1
->u4
.AweAllocation
= 0;
544 /* Increase available pages */
547 /* Check if we've reached the configured low memory threshold */
548 if (MmAvailablePages
== MmLowMemoryThreshold
)
550 /* Clear the event, because now we're ABOVE the threshold */
551 KeClearEvent(MiLowMemoryEvent
);
553 else if (MmAvailablePages
== MmHighMemoryThreshold
)
555 /* Otherwise check if we reached the high threshold and signal the event */
556 KeSetEvent(MiHighMemoryEvent
, 0, FALSE
);
559 #if 0 // When using ARM3 PFN
560 /* Get the page color */
561 Color
= PageFrameIndex
& MmSecondaryColorMask
;
563 /* Get the first page on the color list */
564 ColorTable
= &MmFreePagesByColor
[FreePageList
][Color
];
565 if (ColorTable
->Flink
== LIST_HEAD
)
567 /* The list is empty, so we are the first page */
568 Pfn1
->u4
.PteFrame
= -1;
569 ColorTable
->Flink
= PageFrameIndex
;
573 /* Get the previous page */
574 Blink
= (PMMPFN
)ColorTable
->Blink
;
576 /* Make it link to us */
577 Pfn1
->u4
.PteFrame
= MI_PFNENTRY_TO_PFN(Blink
);
578 Blink
->OriginalPte
.u
.Long
= PageFrameIndex
;
581 /* Now initialize our own list pointers */
582 ColorTable
->Blink
= Pfn1
;
583 Pfn1
->OriginalPte
.u
.Long
= LIST_HEAD
;
585 /* And increase the count in the colored list */
589 /* Notify zero page thread if enough pages are on the free list now */
590 extern KEVENT ZeroPageThreadEvent
;
591 if ((MmFreePageListHead
.Total
> 8) && !(KeReadStateEvent(&ZeroPageThreadEvent
)))
593 /* This is ReactOS-specific */
594 KeSetEvent(&ZeroPageThreadEvent
, IO_NO_INCREMENT
, FALSE
);
600 MiInitializePfn(IN PFN_NUMBER PageFrameIndex
,
601 IN PMMPTE PointerPte
,
606 PMMPTE PointerPtePte
;
607 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
610 Pfn1
= MiGetPfnEntry(PageFrameIndex
);
611 Pfn1
->PteAddress
= PointerPte
;
613 /* Check if this PFN is part of a valid address space */
614 if (PointerPte
->u
.Hard
.Valid
== 1)
620 /* Otherwise this is a fresh page -- set it up */
621 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
== 0);
622 Pfn1
->u3
.e2
.ReferenceCount
= 1;
623 Pfn1
->u2
.ShareCount
= 1;
624 Pfn1
->u3
.e1
.PageLocation
= ActiveAndValid
;
625 ASSERT(Pfn1
->u3
.e1
.Rom
== 0);
626 Pfn1
->u3
.e1
.Modified
= Modified
;
628 /* Get the page table for the PTE */
629 PointerPtePte
= MiAddressToPte(PointerPte
);
630 if (PointerPtePte
->u
.Hard
.Valid
== 0)
632 /* Make sure the PDE gets paged in properly */
633 Status
= MiCheckPdeForPagedPool(PointerPte
);
634 if (!NT_SUCCESS(Status
))
637 KeBugCheckEx(MEMORY_MANAGEMENT
,
639 (ULONG_PTR
)PointerPte
,
640 (ULONG_PTR
)PointerPtePte
->u
.Long
,
641 (ULONG_PTR
)MiPteToAddress(PointerPte
));
645 /* Get the PFN for the page table */
646 PageFrameIndex
= PFN_FROM_PTE(PointerPtePte
);
647 ASSERT(PageFrameIndex
!= 0);
648 Pfn1
->u4
.PteFrame
= PageFrameIndex
;
650 /* Increase its share count so we don't get rid of it */
651 Pfn1
= MiGetPfnEntry(PageFrameIndex
);
652 Pfn1
->u2
.ShareCount
++;
657 MiAllocatePfn(IN PMMPTE PointerPte
,
661 PFN_NUMBER PageFrameIndex
;
664 /* Make an empty software PTE */
665 MI_MAKE_SOFTWARE_PTE(&TempPte
, MM_READWRITE
);
667 /* Lock the PFN database */
668 OldIrql
= KeAcquireQueuedSpinLock(LockQueuePfnLock
);
670 /* Check if we're running low on pages */
671 if (MmAvailablePages
< 128)
673 DPRINT1("Warning, running low on memory: %d pages left\n", MmAvailablePages
);
674 //MiEnsureAvailablePageOrWait(NULL, OldIrql);
678 ASSERT_LIST_INVARIANT(&MmFreePageListHead
);
679 ASSERT_LIST_INVARIANT(&MmZeroedPageListHead
);
680 PageFrameIndex
= MiRemoveAnyPage(0);
682 /* Write the software PTE */
683 ASSERT(PointerPte
->u
.Hard
.Valid
== 0);
684 *PointerPte
= TempPte
;
685 PointerPte
->u
.Soft
.Protection
|= Protection
;
687 /* Initialize its PFN entry */
688 MiInitializePfn(PageFrameIndex
, PointerPte
, TRUE
);
690 /* Release the PFN lock and return the page */
691 ASSERT_LIST_INVARIANT(&MmFreePageListHead
);
692 ASSERT_LIST_INVARIANT(&MmZeroedPageListHead
);
693 KeReleaseQueuedSpinLock(LockQueuePfnLock
, OldIrql
);
694 return PageFrameIndex
;
699 MiDecrementShareCount(IN PMMPFN Pfn1
,
700 IN PFN_NUMBER PageFrameIndex
)
702 ASSERT(PageFrameIndex
> 0);
703 ASSERT(MiGetPfnEntry(PageFrameIndex
) != NULL
);
704 ASSERT(Pfn1
== MiGetPfnEntry(PageFrameIndex
));
706 /* Page must be in-use */
707 if ((Pfn1
->u3
.e1
.PageLocation
!= ActiveAndValid
) &&
708 (Pfn1
->u3
.e1
.PageLocation
!= StandbyPageList
))
710 /* Otherwise we have PFN corruption */
711 KeBugCheckEx(PFN_LIST_CORRUPT
,
714 Pfn1
->u3
.e1
.PageLocation
,
718 /* Check if the share count is now 0 */
719 ASSERT(Pfn1
->u2
.ShareCount
< 0xF000000);
720 if (!--Pfn1
->u2
.ShareCount
)
722 /* ReactOS does not handle these */
723 ASSERT(Pfn1
->u3
.e1
.PrototypePte
== 0);
725 /* Put the page in transition */
726 Pfn1
->u3
.e1
.PageLocation
= TransitionPage
;
728 /* PFN lock must be held */
729 ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL
);
731 /* Page should at least have one reference */
732 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
!= 0);
733 if (Pfn1
->u3
.e2
.ReferenceCount
== 1)
735 /* In ReactOS, this path should always be hit with a deleted PFN */
736 ASSERT(MI_IS_PFN_DELETED(Pfn1
) == TRUE
);
738 /* Clear the last reference */
739 Pfn1
->u3
.e2
.ReferenceCount
= 0;
742 * OriginalPte is used by AweReferenceCount in ReactOS, but either
743 * ways we shouldn't be seeing RMAP entries at this point
745 ASSERT(Pfn1
->OriginalPte
.u
.Soft
.Prototype
== 0);
746 ASSERT(Pfn1
->OriginalPte
.u
.Long
== 0);
748 /* Mark the page temporarily as valid, we're going to make it free soon */
749 Pfn1
->u3
.e1
.PageLocation
= ActiveAndValid
;
751 /* Bring it back into the free list */
752 MiInsertPageInFreeList(PageFrameIndex
);
756 /* Otherwise, just drop the reference count */
757 InterlockedDecrement16((PSHORT
)&Pfn1
->u3
.e2
.ReferenceCount
);
764 MiInitializePfnForOtherProcess(IN PFN_NUMBER PageFrameIndex
,
765 IN PMMPTE PointerPte
,
766 IN PFN_NUMBER PteFrame
)
771 Pfn1
= MiGetPfnEntry(PageFrameIndex
);
772 Pfn1
->PteAddress
= PointerPte
;
774 #if 0 // When using ARM3 PFN
775 /* Make this a software PTE */
776 MI_MAKE_SOFTWARE_PTE(&Pfn1
->OriginalPte
, MM_READWRITE
);
780 ASSERT(Pfn1
->u3
.e2
.ReferenceCount
== 0);
781 Pfn1
->u3
.e2
.ReferenceCount
= 1;
782 Pfn1
->u2
.ShareCount
= 1;
783 Pfn1
->u3
.e1
.PageLocation
= ActiveAndValid
;
784 Pfn1
->u3
.e1
.Modified
= TRUE
;
785 Pfn1
->u4
.InPageError
= FALSE
;
787 /* Did we get a PFN for the page table */
791 Pfn1
->u4
.PteFrame
= PteFrame
;
793 /* Increase its share count so we don't get rid of it */
794 Pfn1
= MiGetPfnEntry(PteFrame
);
795 Pfn1
->u2
.ShareCount
++;