Author: sir_richard
Date: Mon Sep 27 17:36:54 2010
New Revision: 48910
URL:
http://svn.reactos.org/svn/reactos?rev=48910&view=rev
Log:
[NTOS]: Adding colored page lists means we need to start using the OriginalPte field as a
forward/back link. This is shared with AweReferenceCount, which ReactOS uses as the RMAP
list head. However, RMAPped pages shoudl never be free/zero, and non-free-zero pages will
never have a color backlink in OriginalPte, so it should theoretically be safe to do this.
However, it's possible for the RMAP "get" function to be called on a
free/zero page (which would normally return NULL), but with color chaining enabled, the
"get" function would misinterpret the backlink as an RMAP entry. Therefore, we
overload the ParityError bit to signify "there is an RMAP". The get/set
functions now handle this, and the color linkage will ASSERT this later. This way, a
colorlink with ParityError == FALSE is not treated as an rmap list head.
Modified:
trunk/reactos/ntoskrnl/mm/freelist.c
Modified: trunk/reactos/ntoskrnl/mm/freelist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/freelist.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/freelist.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/freelist.c [iso-8859-1] Mon Sep 27 17:36:54 2010
@@ -432,25 +432,68 @@
NTAPI
MmSetRmapListHeadPage(PFN_NUMBER Pfn, struct _MM_RMAP_ENTRY* ListHead)
{
- KIRQL oldIrql;
-
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- MiGetPfnEntry(Pfn)->RmapListHead = (LONG)ListHead;
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+ KIRQL oldIrql;
+ PMMPFN Pfn1;
+
+ oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ Pfn1 = MiGetPfnEntry(Pfn);
+ if (ListHead)
+ {
+ /* Should not be trying to insert an RMAP for a non-active page */
+ ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
+
+ /* Set the list head address */
+ Pfn1->RmapListHead = (LONG)ListHead;
+
+ /* Mark that the page has an actual RMAP, not a residual color link */
+ Pfn1->u3.e1.ParityError = TRUE;
+ }
+ else
+ {
+ /* ReactOS semantics dictate the page is STILL active right now */
+ ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
+
+ /* In this case, the RMAP is actually being removed, so clear field */
+ Pfn1->RmapListHead = 0;
+
+ /* Mark that the page has no RMAP, not a residual color link */
+ Pfn1->u3.e1.ParityError = FALSE;
+
+ /* ReactOS semantics will now release the page, which will make it free and enter
a colored list */
+ }
+
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
}
struct _MM_RMAP_ENTRY*
NTAPI
MmGetRmapListHeadPage(PFN_NUMBER Pfn)
{
- KIRQL oldIrql;
- struct _MM_RMAP_ENTRY* ListHead;
-
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- ListHead = (struct _MM_RMAP_ENTRY*)MiGetPfnEntry(Pfn)->RmapListHead;
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
-
- return(ListHead);
+ KIRQL oldIrql;
+ struct _MM_RMAP_ENTRY* ListHead;
+ PMMPFN Pfn1;
+
+ /* Lock PFN database */
+ oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+
+ /* Get the entry */
+ Pfn1 = MiGetPfnEntry(Pfn);
+
+ /* Check if the page doesn't really have an RMAP */
+ if (Pfn1->u3.e1.ParityError == FALSE)
+ {
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+ return NULL;
+ }
+
+ ListHead = (struct _MM_RMAP_ENTRY*)Pfn1->RmapListHead;
+
+ /* Should not have an RMAP for a non-active page */
+ ASSERT(MiIsPfnInUse(Pfn1) == TRUE);
+
+ /* Release PFN database and return rmap list head */
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+ return ListHead;
}
VOID