From b2730a4d6162cb64fcc214d5a311ce2cad89fb63 Mon Sep 17 00:00:00 2001 From: David Welch Date: Sun, 13 Jul 2003 14:36:32 +0000 Subject: [PATCH] - Fixed deadlock in pager thread. - Added some more debugging checks. svn path=/trunk/; revision=5107 --- reactos/ntoskrnl/include/internal/mm.h | 4 +++ reactos/ntoskrnl/mm/balance.c | 7 ++---- reactos/ntoskrnl/mm/freelist.c | 34 ++++++++++++++++++++++++-- reactos/ntoskrnl/mm/i386/page.c | 34 +++++++++++++++++++++++++- reactos/ntoskrnl/mm/mminit.c | 4 +-- reactos/ntoskrnl/mm/pager.c | 25 ++++++++++++------- 6 files changed, 89 insertions(+), 19 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 76e4cb53a29..589961b4e0b 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -640,5 +640,9 @@ VOID MiStartPagerThread(VOID); VOID MmSetLRULastPage(PHYSICAL_ADDRESS PhysicalAddress); +VOID +MmRawDeleteVirtualMapping(PVOID Address); +VOID +MiStopPagerThread(VOID); #endif diff --git a/reactos/ntoskrnl/mm/balance.c b/reactos/ntoskrnl/mm/balance.c index 16faafa78df..d9cab82022b 100644 --- a/reactos/ntoskrnl/mm/balance.c +++ b/reactos/ntoskrnl/mm/balance.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: balance.c,v 1.18 2003/07/12 01:52:10 dwelch Exp $ +/* $Id: balance.c,v 1.19 2003/07/13 14:36:32 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/balance.c @@ -181,10 +181,6 @@ MmRebalanceMemoryConsumers(VOID) Target = Target - NrFreedPages; } } - if (Target > 0) - { - KeBugCheck(0); - } } NTSTATUS @@ -264,6 +260,7 @@ MmRequestPageMemoryConsumer(ULONG Consumer, BOOLEAN CanWait, MmTransferOwnershipPage(Page, Consumer); *AllocatedPage = Page; InterlockedDecrement((LONG *)&MiPagesRequired); + MiStopPagerThread(); return(STATUS_SUCCESS); } diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index 762100ac95e..85302ff51cf 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -553,6 +553,11 @@ MmMarkPageMapped(PHYSICAL_ADDRESS PhysicalAddress) if (Start < MmPageArraySize) { KeAcquireSpinLock(&PageListLock, &oldIrql); + if (MmPageArray[Start].Flags.Type == MM_PHYSICAL_PAGE_FREE) + { + DbgPrint("Mapping non-used page\n"); + KeBugCheck(0); + } MmPageArray[Start].MapCount++; KeReleaseSpinLock(&PageListLock, oldIrql); } @@ -563,10 +568,20 @@ MmMarkPageUnmapped(PHYSICAL_ADDRESS PhysicalAddress) { ULONG Start = PhysicalAddress.u.LowPart / PAGE_SIZE; KIRQL oldIrql; - + if (Start < MmPageArraySize) { KeAcquireSpinLock(&PageListLock, &oldIrql); + if (MmPageArray[Start].Flags.Type == MM_PHYSICAL_PAGE_FREE) + { + DbgPrint("Unmapping non-used page\n"); + KeBugCheck(0); + } + if (MmPageArray[Start].MapCount == 0) + { + DbgPrint("Unmapping not mapped page\n"); + KeBugCheck(0); + } MmPageArray[Start].MapCount--; KeReleaseSpinLock(&PageListLock, oldIrql); } @@ -620,7 +635,7 @@ MmReferencePage(PHYSICAL_ADDRESS PhysicalAddress) KIRQL oldIrql; DPRINT("MmReferencePage(PhysicalAddress %x)\n", PhysicalAddress); - + if (PhysicalAddress.u.LowPart == 0) { KeBugCheck(0); @@ -871,6 +886,11 @@ MmAllocPage(ULONG Consumer, SWAPENTRY SavedSwapEntry) DbgPrint("Got non-free page from freelist\n"); KeBugCheck(0); } + if (PageDescriptor->MapCount != 0) + { + DbgPrint("Got mapped page from freelist\n"); + KeBugCheck(0); + } PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_USED; PageDescriptor->Flags.Consumer = Consumer; PageDescriptor->ReferenceCount = 1; @@ -891,6 +911,11 @@ MmAllocPage(ULONG Consumer, SWAPENTRY SavedSwapEntry) { MiZeroPage(PageOffset); } + if (PageDescriptor->MapCount != 0) + { + DbgPrint("Returning mapped page.\n"); + KeBugCheck(0); + } return(PageOffset); } @@ -953,6 +978,11 @@ MmZeroPageThreadMain(PVOID Ignored) memset(Address, 0, PAGE_SIZE); MmDeleteVirtualMapping(NULL, (PVOID)Address, FALSE, NULL, NULL); KeAcquireSpinLock(&PageListLock, &oldIrql); + if (PageDescriptor->MapCount != 0) + { + DbgPrint("Mapped page on freelist.\n"); + KeBugCheck(0); + } PageDescriptor->Flags.Type = MM_PHYSICAL_PAGE_FREE; InsertHeadList(&FreeZeroedPageListHead, ListEntry); } diff --git a/reactos/ntoskrnl/mm/i386/page.c b/reactos/ntoskrnl/mm/i386/page.c index 7b72089b96b..01f8634e79f 100644 --- a/reactos/ntoskrnl/mm/i386/page.c +++ b/reactos/ntoskrnl/mm/i386/page.c @@ -16,7 +16,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* $Id: page.c,v 1.54 2003/07/11 01:23:15 royce Exp $ +/* $Id: page.c,v 1.55 2003/07/13 14:36:32 dwelch Exp $ * * PROJECT: ReactOS kernel * FILE: ntoskrnl/mm/i386/page.c @@ -442,6 +442,38 @@ MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, PHYSIC } } +VOID +MmRawDeleteVirtualMapping(PVOID Address) +{ + PULONG Pde, kePde; + + /* + * Set the page directory entry, we may have to copy the entry from + * the global page directory. + */ + Pde = ADDR_TO_PDE(Address); + if (*Pde == 0 && Address >= (PVOID)KERNEL_BASE) + { + kePde = MmGlobalKernelPageDirectory + ADDR_TO_PDE_OFFSET(Address); + if (*kePde != 0) + { + *Pde = *kePde; + FLUSH_TLB; + } + } + + if (*Pde == 0) + { + return; + } + + /* + * Set the entry to zero + */ + *ADDR_TO_PTE(Address) = 0; + FLUSH_TLB; +} + VOID MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage, BOOL* WasDirty, PHYSICAL_ADDRESS* PhysicalAddr) diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index e25636edff1..6ba8e7acae1 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -1,4 +1,4 @@ -/* $Id: mminit.c,v 1.52 2003/07/10 21:05:03 royce Exp $ +/* $Id: mminit.c,v 1.53 2003/07/13 14:36:32 dwelch Exp $ * * COPYRIGHT: See COPYING in the top directory * PROJECT: ReactOS kernel @@ -386,7 +386,7 @@ VOID MmInit1(ULONG FirstKrnlPhysAddr, i<(KERNEL_BASE + 2 * PAGE_TABLE_SIZE); i=i+PAGE_SIZE) { - MmDeleteVirtualMapping(NULL, (PVOID)(i), FALSE, NULL, NULL); + MmRawDeleteVirtualMapping((PVOID)(i)); } DPRINT("Almost done MmInit()\n"); #ifndef MP diff --git a/reactos/ntoskrnl/mm/pager.c b/reactos/ntoskrnl/mm/pager.c index 708a1ca69f8..1a63dd5605f 100644 --- a/reactos/ntoskrnl/mm/pager.c +++ b/reactos/ntoskrnl/mm/pager.c @@ -1,4 +1,4 @@ -/* $Id: pager.c,v 1.12 2003/07/12 01:52:10 dwelch Exp $ +/* $Id: pager.c,v 1.13 2003/07/13 14:36:32 dwelch Exp $ * * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS kernel @@ -25,7 +25,7 @@ static HANDLE PagerThreadHandle; static CLIENT_ID PagerThreadId; static KEVENT PagerThreadEvent; static BOOLEAN PagerThreadShouldTerminate; -static ULONG PagerThreadWorking; +static ULONG PagerThreadWorkCount; /* FUNCTIONS *****************************************************************/ @@ -40,13 +40,19 @@ MiStartPagerThread(VOID) { ULONG WasWorking; - WasWorking = InterlockedExchange(&PagerThreadWorking, 1); - if (WasWorking == 0) + WasWorking = InterlockedIncrement(&PagerThreadWorkCount); + if (WasWorking == 1) { KeSetEvent(&PagerThreadEvent, IO_NO_INCREMENT, FALSE); } } +VOID +MiStopPagerThread(VOID) +{ + (VOID)InterlockedDecrement(&PagerThreadWorkCount); +} + static NTSTATUS STDCALL MmPagerThreadMain(PVOID Ignored) { @@ -70,10 +76,11 @@ MmPagerThreadMain(PVOID Ignored) DbgPrint("PagerThread: Terminating\n"); return(STATUS_SUCCESS); } - /* Try and make some memory available to the system. */ - MmRebalanceMemoryConsumers(); - /* Let the rest of the system know we finished this run. */ - (VOID)InterlockedExchange(&PagerThreadWorking, 0); + do + { + /* Try and make some memory available to the system. */ + MmRebalanceMemoryConsumers(); + } while(PagerThreadWorkCount > 0); } } @@ -82,7 +89,7 @@ NTSTATUS MmInitPagerThread(VOID) NTSTATUS Status; PagerThreadShouldTerminate = FALSE; - PagerThreadWorking = 0; + PagerThreadWorkCount = 0; KeInitializeEvent(&PagerThreadEvent, SynchronizationEvent, FALSE);