Author: sir_richard
Date: Fri Feb 19 18:54:16 2010
New Revision: 45621
URL: http://svn.reactos.org/svn/reactos?rev=45621&view=rev
Log:
[NTOS]: Fix an off-by-one-error which incorrectly causes GUI promotion to fail if the first GUI call is "0", since the limit on the GUI descriptor table will also be "0". We should check if the limit is equal to or lower, not just if it's lower.
Thanks to Physicus and Fireball for reporting and working this out. Should fix the "ArwinSS" problem.
Modified:
trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
Modified: trunk/reactos/ntoskrnl/ke/i386/traphdlr.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/traphdlr.…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/ke/i386/traphdlr.c [iso-8859-1] Fri Feb 19 18:54:16 2010
@@ -1401,7 +1401,7 @@
DescriptorTable = (PVOID)((ULONG_PTR)Thread->ServiceTable + Offset);
/* Validate the system call number */
- if (__builtin_expect(Id > DescriptorTable->Limit, 0))
+ if (__builtin_expect(Id >= DescriptorTable->Limit, 0))
{
/* Check if this is a GUI call */
if (__builtin_expect(!(Offset & SERVICE_TABLE_TEST), 0))
Author: sir_richard
Date: Fri Feb 19 18:45:10 2010
New Revision: 45620
URL: http://svn.reactos.org/svn/reactos?rev=45620&view=rev
Log:
[NTOS]: Fix off-by-one error in MDL locking which caused the last PFN not to be referenced if it was part of a locked MDL, because it was assumed to be "higher than the last PFN". This further caused the entire MDL to be incorrectly treated as an I/O space mapping. Later, when unlocked, the last PFN's reference count would drop to 0, and the virtual memory range that had been locked would now be using a freed page, that would get re-used later. Noticed this bug because my WC changes allocation strategies to increase the chance of pages at the end to be used, ans the last PFN was being used a lot due to this.
Modified:
trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c
Modified: trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/ARM3/mdlsup.c [iso-8859-1] Fri Feb 19 18:45:10 2010
@@ -954,7 +954,7 @@
// Grab the PFN
//
PageFrameIndex = PFN_FROM_PTE(PointerPte);
- if (PageFrameIndex < MmHighestPhysicalPage)
+ if (PageFrameIndex <= MmHighestPhysicalPage)
{
//
// Get the PFN entry
Author: sir_richard
Date: Fri Feb 19 01:46:35 2010
New Revision: 45616
URL: http://svn.reactos.org/svn/reactos?rev=45616&view=rev
Log:
[NTOS]: Instead of having an LRU linked list of working set pages, we instead have a bitmap.
Advantage: Pages are only in a linked list when they are NOT active (free/zeroed, for now). This makes the LIST_ENTRY fields usable when a page is active, so we can store data in there. This will make it easier to sync our PFN format with Windows.
Advantage: It's a lot faster to set/clear bits than to do list operations (both still O1 though). Scanning for the bit is a bit slower than parsing a list, on the other hand, so it's a toss.
Disadvantage: We lose LRU, which in theory makes us cannibalize working sets randomly instead of by-usage. However, considering the speed of ReactOS paging, and the effects of canabalizing the WS in the first place, I doubt this is really a problem.
The main point of this is advantage #1 -- making used pages not be on any lists. This will allow us to almost 100% sync the PFN layouts, which will lead to the eventual negation of any temporary disavantages.
Modified:
trunk/reactos/ntoskrnl/mm/balance.c
trunk/reactos/ntoskrnl/mm/freelist.c
trunk/reactos/ntoskrnl/mm/mminit.c
Modified: trunk/reactos/ntoskrnl/mm/balance.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/balance.c?rev=…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/balance.c [iso-8859-1] Fri Feb 19 01:46:35 2010
@@ -187,11 +187,6 @@
DPRINT("Succeeded\n");
Target--;
(*NrFreedPages)++;
- }
- else if (Status == STATUS_PAGEFILE_QUOTA)
- {
- MmRemoveLRUUserPage(CurrentPage);
- MmInsertLRULastUserPage(CurrentPage);
}
CurrentPage = NextPage;
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] Fri Feb 19 01:46:35 2010
@@ -74,71 +74,81 @@
/* FUNCTIONS *************************************************************/
+static RTL_BITMAP MiUserPfnBitMap;
+
+/* FUNCTIONS *************************************************************/
+
+VOID
+NTAPI
+MiInitializeUserPfnBitmap(VOID)
+{
+ PVOID Bitmap;
+
+ /* Allocate enough buffer for the PFN bitmap and align it on 32-bits */
+ Bitmap = ExAllocatePoolWithTag(NonPagedPool,
+ (((MmHighestPhysicalPage + 1) + 31) / 32) * 4,
+ ' mM');
+ ASSERT(Bitmap);
+
+ /* Initialize it and clear all the bits to begin with */
+ RtlInitializeBitMap(&MiUserPfnBitMap,
+ Bitmap,
+ MmHighestPhysicalPage + 1);
+ RtlClearAllBits(&MiUserPfnBitMap);
+}
+
PFN_TYPE
NTAPI
MmGetLRUFirstUserPage(VOID)
{
- PLIST_ENTRY NextListEntry;
- PHYSICAL_PAGE* PageDescriptor;
- KIRQL oldIrql;
-
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- NextListEntry = UserPageListHead.Flink;
- if (NextListEntry == &UserPageListHead)
- {
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
- return 0;
- }
- PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
- return PageDescriptor - MmPfnDatabase[0];
+ ULONG Position;
+ KIRQL OldIrql;
+
+ /* Find the first user page */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ Position = RtlFindSetBits(&MiUserPfnBitMap, 1, 0);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ if (Position == 0xFFFFFFFF) return 0;
+
+ /* Return it */
+ return Position;
}
VOID
NTAPI
MmInsertLRULastUserPage(PFN_TYPE Pfn)
{
- KIRQL oldIrql;
- PPHYSICAL_PAGE Page;
-
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- Page = MiGetPfnEntry(Pfn);
-// if (!Page->Consumer != MC_USER) DPRINT1("Page Consumer: %d\n", Page->Consumer);
- ASSERT(Page->Consumer == MC_USER);
- ASSERT(Page->u3.e1.PageLocation = ActiveAndValid);
- InsertTailList(&UserPageListHead, &Page->ListEntry);
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
+ KIRQL OldIrql;
+
+ /* Set the page as a user page */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ RtlSetBit(&MiUserPfnBitMap, Pfn);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
}
PFN_TYPE
NTAPI
MmGetLRUNextUserPage(PFN_TYPE PreviousPfn)
{
- PLIST_ENTRY NextListEntry;
- PHYSICAL_PAGE* PageDescriptor;
- KIRQL oldIrql;
- PPHYSICAL_PAGE Page;
-
- oldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
- Page = MiGetPfnEntry(PreviousPfn);
- ASSERT(Page->Consumer == MC_USER);
- ASSERT(Page->u3.e1.PageLocation = ActiveAndValid);
- NextListEntry = (PLIST_ENTRY)Page->ListEntry.Flink;
- if (NextListEntry == &UserPageListHead)
- {
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
- return 0;
- }
- PageDescriptor = CONTAINING_RECORD(NextListEntry, PHYSICAL_PAGE, ListEntry);
- KeReleaseQueuedSpinLock(LockQueuePfnLock, oldIrql);
- return PageDescriptor - MmPfnDatabase[0];
+ ULONG Position;
+ KIRQL OldIrql;
+
+ /* Find the next user page */
+ OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
+ Position = RtlFindSetBits(&MiUserPfnBitMap, 1, PreviousPfn + 1);
+ KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
+ if (Position == 0xFFFFFFFF) return 0;
+
+ /* Return it */
+ return Position;
}
VOID
NTAPI
MmRemoveLRUUserPage(PFN_TYPE Page)
{
- RemoveEntryList(&MiGetPfnEntry(Page)->ListEntry);
+ /* Unset the page as a user page */
+ RtlClearBit(&MiUserPfnBitMap, Page);
}
BOOLEAN
@@ -907,7 +917,6 @@
if (Page->u3.e2.ReferenceCount == 0)
{
MmAvailablePages++;
- if (Page->Consumer == MC_USER) RemoveEntryList(&Page->ListEntry);
Page->u3.e1.PageLocation = FreePageList;
InsertTailList(&FreeUnzeroedPageListHead,
&Page->ListEntry);
Modified: trunk/reactos/ntoskrnl/mm/mminit.c
URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?rev=4…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/mminit.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/mminit.c [iso-8859-1] Fri Feb 19 01:46:35 2010
@@ -349,6 +349,8 @@
DPRINT1("Total: %08lX (%d MB)\n", TotalPages, (TotalPages * PAGE_SIZE) / 1024 / 1024);
}
+VOID NTAPI MiInitializeUserPfnBitmap(VOID);
+
BOOLEAN
NTAPI
MmInitSystem(IN ULONG Phase,
@@ -397,6 +399,7 @@
MmInitializePagedPool();
/* Initialize working sets */
+ MiInitializeUserPfnBitmap();
MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory);
/* Initialize the user mode image list */