From 3c027e728c0735e92b34e9fb28f245d3c31874f4 Mon Sep 17 00:00:00 2001 From: ReactOS Portable Systems Group Date: Sat, 2 Jan 2010 16:17:48 +0000 Subject: [PATCH] - Switch to using ARM3 paged pool -- all pool allocations are now handled by ARM3, which should be much more efficient, and combines both NP and P code together. svn path=/trunk/; revision=44885 --- reactos/ntoskrnl/ex/sysinfo.c | 2 +- reactos/ntoskrnl/mm/ARM3/expool.c | 30 +- reactos/ntoskrnl/mm/dbgpool.c | 134 --- reactos/ntoskrnl/mm/mminit.c | 90 +- reactos/ntoskrnl/mm/pool.c | 236 ----- reactos/ntoskrnl/mm/ppool.c | 243 ----- reactos/ntoskrnl/mm/rpoolmgr.h | 1060 ---------------------- reactos/ntoskrnl/ntoskrnl-generic.rbuild | 3 - 8 files changed, 24 insertions(+), 1774 deletions(-) delete mode 100644 reactos/ntoskrnl/mm/dbgpool.c delete mode 100644 reactos/ntoskrnl/mm/pool.c delete mode 100644 reactos/ntoskrnl/mm/ppool.c delete mode 100644 reactos/ntoskrnl/mm/rpoolmgr.h diff --git a/reactos/ntoskrnl/ex/sysinfo.c b/reactos/ntoskrnl/ex/sysinfo.c index c04886dae41..b59443680c5 100644 --- a/reactos/ntoskrnl/ex/sysinfo.c +++ b/reactos/ntoskrnl/ex/sysinfo.c @@ -594,7 +594,7 @@ QSI_DEF(SystemPerformanceInformation) Spi->Spare3Count = 0; /* FIXME */ Spi->ResidentSystemCachePage = MiMemoryConsumers[MC_CACHE].PagesUsed; - Spi->ResidentPagedPoolPage = MmPagedPoolSize; /* FIXME */ + Spi->ResidentPagedPoolPage = MiMemoryConsumers[MC_PPOOL].PagesUsed; /* FIXME */ Spi->ResidentSystemDriverPage = 0; /* FIXME */ Spi->CcFastReadNoWait = 0; /* FIXME */ diff --git a/reactos/ntoskrnl/mm/ARM3/expool.c b/reactos/ntoskrnl/mm/ARM3/expool.c index a8fe5f39869..d8cf8642eca 100644 --- a/reactos/ntoskrnl/mm/ARM3/expool.c +++ b/reactos/ntoskrnl/mm/ARM3/expool.c @@ -178,11 +178,14 @@ ExUnlockPool(IN PPOOL_DESCRIPTOR Descriptor, /* PUBLIC FUNCTIONS ***********************************************************/ +/* + * @implemented + */ PVOID NTAPI -ExAllocateArmPoolWithTag(IN POOL_TYPE PoolType, - IN SIZE_T NumberOfBytes, - IN ULONG Tag) +ExAllocatePoolWithTag(IN POOL_TYPE PoolType, + IN SIZE_T NumberOfBytes, + IN ULONG Tag) { PPOOL_DESCRIPTOR PoolDesc; PLIST_ENTRY ListHead; @@ -449,10 +452,13 @@ ExAllocateArmPoolWithTag(IN POOL_TYPE PoolType, return ++Entry; } +/* + * @implemented + */ PVOID NTAPI -ExAllocateArmPool(POOL_TYPE PoolType, - SIZE_T NumberOfBytes) +ExAllocatePool(POOL_TYPE PoolType, + SIZE_T NumberOfBytes) { // // Use a default tag of "None" @@ -460,10 +466,13 @@ ExAllocateArmPool(POOL_TYPE PoolType, return ExAllocatePoolWithTag(PoolType, NumberOfBytes, 'enoN'); } +/* + * @implemented + */ VOID NTAPI -ExFreeArmPoolWithTag(IN PVOID P, - IN ULONG TagToFree) +ExFreePoolWithTag(IN PVOID P, + IN ULONG TagToFree) { PPOOL_HEADER Entry, NextEntry; ULONG BlockSize; @@ -633,14 +642,17 @@ ExFreeArmPoolWithTag(IN PVOID P, ExUnlockPool(PoolDesc, OldIrql); } +/* + * @implemented + */ VOID NTAPI -ExFreeArmPool(PVOID P) +ExFreePool(PVOID P) { // // Just free without checking for the tag // - ExFreeArmPoolWithTag(P, 0); + ExFreePoolWithTag(P, 0); } /* diff --git a/reactos/ntoskrnl/mm/dbgpool.c b/reactos/ntoskrnl/mm/dbgpool.c deleted file mode 100644 index 86f9639bde8..00000000000 --- a/reactos/ntoskrnl/mm/dbgpool.c +++ /dev/null @@ -1,134 +0,0 @@ -/* - * PROJECT: ReactOS Kernel - * LICENSE: GPL - See COPYING in the top level directory - * FILE: ntoskrnl/mm/dbgpool.c - * PURPOSE: Debug version of a pool allocator - * PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org) - */ - -/* INCLUDES ***************************************************************/ - -#include -#define NDEBUG -#include - -/* FUNCTIONS **************************************************************/ - -typedef struct _EI_WHOLE_PAGE_HEADER { - PVOID ActualAddress; - ULONG Size; - ULONG Tag; -} EI_WHOLE_PAGE_HEADER, *PEI_WHOLE_PAGE_HEADER; - -BOOLEAN -NTAPI -ExpIsPoolTagDebuggable(ULONG Tag) -{ -#if 0 - if (Tag == 'llaC') return FALSE; - if (Tag == 'virD') return FALSE; - if (Tag == 'iveD') return FALSE; - if (Tag == 'padA') return FALSE; - - if (Tag == 'dSeS') return FALSE; - if (Tag == 'iDbO') return FALSE; - if (Tag == 'mNbO') return FALSE; - if (Tag == 'DNbO') return FALSE; - if (Tag == 'btbO') return FALSE; - if (Tag == 'cSbO') return FALSE; - //if (Tag == 'iSeS') return FALSE; - //if (Tag == 'cAeS') return FALSE; -#endif - - return TRUE; -} - - -PVOID -NTAPI -ExpAllocateDebugPool(POOL_TYPE Type, ULONG Size, ULONG Tag, PVOID Caller, BOOLEAN EndOfPage) -{ - ULONG UserSize, TotalSize, AlignedSize; - ULONG_PTR UserData, GuardArea; - PEI_WHOLE_PAGE_HEADER Header; - ULONG_PTR Buffer; - - /* Calculate sizes */ - AlignedSize = ROUND_UP(Size, MM_POOL_ALIGNMENT); - UserSize = AlignedSize + sizeof(EI_WHOLE_PAGE_HEADER); - TotalSize = UserSize + 2*PAGE_SIZE; - - /* Right now we support only end-of-page allocations */ - ASSERT(EndOfPage); - - /* Allocate space using default routine */ - if (Type & PAGED_POOL_MASK) - { - Buffer = (ULONG_PTR) - ExAllocatePagedPoolWithTag(Type, TotalSize, Tag); - } - else - { - ASSERT(FALSE); - return NULL; - } - - - /* If allocation failed - fail too */ - if (!Buffer) - { - DPRINT1("A big problem! Pool allocation failed!\n"); - return NULL; - } - - /* Calculate guard area as placed on a page boundary - * at the end of allocated area */ - GuardArea = PAGE_ROUND_DOWN(Buffer + TotalSize - PAGE_SIZE + 1); - - /* Calculate user data and header pointers */ - UserData = GuardArea - AlignedSize; - Header = (PEI_WHOLE_PAGE_HEADER)(UserData - sizeof(EI_WHOLE_PAGE_HEADER)); - - /* Fill out the header */ - Header->ActualAddress = (PVOID)Buffer; - Header->Tag = Tag; - Header->Size = AlignedSize; - - /* Protect the guard page */ - MmSetPageProtect(NULL, (PVOID)GuardArea, PAGE_NOACCESS); - - DPRINT("Allocating whole page block Tag %c%c%c%c, Buffer %p, Header %p, UserData %p, GuardArea %p, Size %d\n", - Tag & 0xFF, (Tag >> 8) & 0xFF, - (Tag >> 16) & 0xFF, (Tag >> 24) & 0xFF, - Buffer, Header, UserData, GuardArea, Size); - - return (PVOID)UserData; -} - -VOID -NTAPI -ExpFreeDebugPool(PVOID Block, BOOLEAN PagedPool) -{ - PEI_WHOLE_PAGE_HEADER Header; - PVOID ProtectedPage; - - /* Get pointer to our special header */ - Header = (PEI_WHOLE_PAGE_HEADER) - (((PCHAR)Block) - sizeof(EI_WHOLE_PAGE_HEADER)); - - DPRINT("Freeing whole page block at %08x (Tag %c%c%c%c, %x Header %x)\n", Block, - Header->Tag & 0xFF, (Header->Tag >> 8) & 0xFF, - (Header->Tag >> 16) & 0xFF, (Header->Tag >> 24) & 0xFF, Header->Tag, Header); - - /* Calculate protected page adresss */ - ProtectedPage = ((PCHAR)Block) + Header->Size; - - /* Unprotect it */ - MmSetPageProtect(NULL, ProtectedPage, PAGE_READWRITE); - - /* Free storage */ - ASSERT(PagedPool); - ExFreePagedPool(Header->ActualAddress); -} - -/* EOF */ diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index c9a837dd678..50b93ea04b7 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -198,21 +198,6 @@ MiInitSystemMemoryAreas() BoundaryAddressMultiple); ASSERT(Status == STATUS_SUCCESS); - // - // And now, ReactOS paged pool - // - BaseAddress = MmPagedPoolBase; - Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), - MEMORY_AREA_PAGED_POOL | MEMORY_AREA_STATIC, - &BaseAddress, - MmPagedPoolSize, - PAGE_READWRITE, - &MArea, - TRUE, - 0, - BoundaryAddressMultiple); - ASSERT(Status == STATUS_SUCCESS); - // // Next, the KPCR // @@ -287,10 +272,6 @@ MiDbgDumpAddressSpace(VOID) MmSystemRangeStart, (ULONG_PTR)MmSystemRangeStart + MmBootImageSize, "Boot Loaded Image"); - DPRINT1(" 0x%p - 0x%p\t%s\n", - MmPagedPoolBase, - (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize, - "Paged Pool"); DPRINT1(" 0x%p - 0x%p\t%s\n", MmPfnDatabase, (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT), @@ -389,80 +370,13 @@ MmInitSystem(IN ULONG Phase, // MiDbgReadyForPhysical = TRUE; #endif - - /* Put the paged pool after the loaded modules */ - MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MmSystemRangeStart + - MmBootImageSize); - MmPagedPoolSize = MM_PAGED_POOL_SIZE; - + /* Intialize system memory areas */ MiInitSystemMemoryAreas(); - // - // STEP 1: Allocate and free a single page, repeatedly - // We should always get the same address back - // - if (1) - { - PULONG Test, OldTest; - ULONG i; - - OldTest = Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE); - ASSERT(Test); - for (i = 0; i < 16; i++) - { - MiFreePoolPages(Test); - Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE); - ASSERT(OldTest == Test); - } - MiFreePoolPages(Test); - } - - // - // STEP 2: Allocate 2048 pages without freeing them - // We should run out of space at 1024 pages, since we don't support - // expansion yet. - // - if (1) - { - PULONG Test[2048]; - ULONG i; - - for (i = 0; i < 2048; i++) - { - Test[i] = MiAllocatePoolPages(PagedPool, PAGE_SIZE); - if (!Test[i]) - { - ASSERT(i == 1024); - break; - } - } - - // - // Cleanup - // - while (--i) if (Test[i]) MiFreePoolPages(Test[i]); - } - - // - // STEP 3: Allocate a page and touch it. - // We should get an ARM3 page fault and it should handle the fault - // - if (1) - { - PULONG Test; - - Test = MiAllocatePoolPages(PagedPool, PAGE_SIZE); - ASSERT(*Test == 0); - MiFreePoolPages(Test); - } - /* Dump the address space */ MiDbgDumpAddressSpace(); - - /* Initialize paged pool */ - MmInitializePagedPool(); - + /* Initialize working sets */ MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); diff --git a/reactos/ntoskrnl/mm/pool.c b/reactos/ntoskrnl/mm/pool.c deleted file mode 100644 index 07132e80e85..00000000000 --- a/reactos/ntoskrnl/mm/pool.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/pool.c - * PURPOSE: Implements the kernel memory pool - * - * PROGRAMMERS: David Welch (welch@mcmail.com) - */ - -/* INCLUDES ****************************************************************/ - -#include - -#define NDEBUG -#include - -/* Uncomment to enable pool overruns debugging. Don't forget to increase - max pool sizes (MM_[NON]PAGED_POOL_SIZE) in include/internal/mm.h */ -//#define DEBUG_NPOOL -//#define DEBUG_PPOOL - -extern PVOID MiNonPagedPoolStart; -extern ULONG MiNonPagedPoolLength; -extern ULONG MmTotalPagedPoolQuota; -extern ULONG MmTotalNonPagedPoolQuota; - -/* FUNCTIONS ***************************************************************/ - -ULONG NTAPI -EiGetPagedPoolTag(IN PVOID Block); - -ULONG NTAPI -EiGetNonPagedPoolTag(IN PVOID Block); - -PVOID -NTAPI -ExAllocateArmPoolWithTag(POOL_TYPE PoolType, - SIZE_T NumberOfBytes, - ULONG Tag); - -static PVOID NTAPI -EiAllocatePool(POOL_TYPE PoolType, - ULONG NumberOfBytes, - ULONG Tag, - PVOID Caller) -{ - PVOID Block; - PCHAR TagChars = (PCHAR)&Tag; - - if (Tag == 0) - KeBugCheckEx(BAD_POOL_CALLER, 0x9b, PoolType, NumberOfBytes, (ULONG_PTR)Caller); - if (Tag == ' GIB') - KeBugCheckEx(BAD_POOL_CALLER, 0x9c, PoolType, NumberOfBytes, (ULONG_PTR)Caller); - -#define IS_LETTER_OR_DIGIT(c) (((c) >= 'a' && (c) <= 'z') || ((c) >= 'A' && (c) <= 'Z') || ((c) >= '0' && (c) <= '9')) - if (!IS_LETTER_OR_DIGIT(TagChars[0]) && - !IS_LETTER_OR_DIGIT(TagChars[1]) && - !IS_LETTER_OR_DIGIT(TagChars[2]) && - !IS_LETTER_OR_DIGIT(TagChars[3])) - KeBugCheckEx(BAD_POOL_CALLER, 0x9d, Tag, PoolType, (ULONG_PTR)Caller); - - /* FIXME: Handle SESSION_POOL_MASK, VERIFIER_POOL_MASK, QUOTA_POOL_MASK */ - if (PoolType & PAGED_POOL_MASK) - { - if (KeGetCurrentIrql() > APC_LEVEL) - KeBugCheckEx(BAD_POOL_CALLER, 0x08, KeGetCurrentIrql(), PoolType, Tag); -#ifdef DEBUG_PPOOL - if (ExpIsPoolTagDebuggable(Tag)) - Block = ExpAllocateDebugPool(PoolType, NumberOfBytes, Tag, Caller, TRUE); - else -#endif - Block = ExAllocatePagedPoolWithTag(PoolType, NumberOfBytes, Tag); - } - else - { - if (KeGetCurrentIrql() > DISPATCH_LEVEL) - KeBugCheckEx(BAD_POOL_CALLER, 0x08, KeGetCurrentIrql(), PoolType, Tag); -#ifdef DEBUG_NPOOL - if (ExpIsPoolTagDebuggable(Tag)) - Block = ExpAllocateDebugPool(PoolType, NumberOfBytes, Tag, Caller, TRUE); - else -#endif - Block = ExAllocateArmPoolWithTag(PoolType, NumberOfBytes, Tag); - } - - if ((PoolType & MUST_SUCCEED_POOL_MASK) && !Block) - KeBugCheckEx(BAD_POOL_CALLER, 0x9a, PoolType, NumberOfBytes, Tag); - return Block; -} - -/* - * @implemented - */ -PVOID NTAPI -ExAllocatePool (POOL_TYPE PoolType, SIZE_T NumberOfBytes) -/* - * FUNCTION: Allocates pool memory of a specified type and returns a pointer - * to the allocated block. This routine is used for general purpose allocation - * of memory - * ARGUMENTS: - * PoolType - * Specifies the type of memory to allocate which can be one - * of the following: - * - * NonPagedPool - * NonPagedPoolMustSucceed - * NonPagedPoolCacheAligned - * NonPagedPoolCacheAlignedMustS - * PagedPool - * PagedPoolCacheAligned - * - * NumberOfBytes - * Specifies the number of bytes to allocate - * RETURNS: The allocated block on success - * NULL on failure - */ -{ - PVOID Block; - -#if defined(__GNUC__) - - Block = EiAllocatePool(PoolType, - NumberOfBytes, - TAG_NONE, - (PVOID)__builtin_return_address(0)); -#elif defined(_MSC_VER) - - Block = EiAllocatePool(PoolType, - NumberOfBytes, - TAG_NONE, - &ExAllocatePool); -#else -#error Unknown compiler -#endif - - return(Block); -} - - -/* - * @implemented - */ -PVOID NTAPI -ExAllocatePoolWithTag (POOL_TYPE PoolType, SIZE_T NumberOfBytes, ULONG Tag) -{ - PVOID Block; - -#if defined(__GNUC__) - - Block = EiAllocatePool(PoolType, - NumberOfBytes, - Tag, - (PVOID)__builtin_return_address(0)); -#elif defined(_MSC_VER) - - Block = EiAllocatePool(PoolType, - NumberOfBytes, - Tag, - &ExAllocatePoolWithTag); -#else -#error Unknown compiler -#endif - - return(Block); -} - -/* - * @implemented - */ -#undef ExFreePool -VOID NTAPI -ExFreePool(IN PVOID Block) -{ - ExFreePoolWithTag(Block, 0); -} - -VOID -NTAPI -ExFreeArmPoolWithTag(PVOID P, - ULONG TagToFree); - -/* - * @implemented - */ -VOID -NTAPI -ExFreePoolWithTag( - IN PVOID Block, - IN ULONG Tag) -{ - /* Check for paged pool */ - if (Block >= MmPagedPoolBase && - (char*)Block < ((char*)MmPagedPoolBase + MmPagedPoolSize)) - { - /* Validate tag */ -#ifndef DEBUG_PPOOL - if (Tag != 0 && Tag != EiGetPagedPoolTag(Block)) - KeBugCheckEx(BAD_POOL_CALLER, - 0x0a, - (ULONG_PTR)Block, - EiGetPagedPoolTag(Block), - Tag); -#endif - /* Validate IRQL */ - if (KeGetCurrentIrql() > APC_LEVEL) - KeBugCheckEx(BAD_POOL_CALLER, - 0x09, - KeGetCurrentIrql(), - PagedPool, - (ULONG_PTR)Block); - - /* Free from paged pool */ -#ifdef DEBUG_PPOOL - if (ExpIsPoolTagDebuggable(Tag)) - ExpFreeDebugPool(Block, TRUE); - else -#endif - ExFreePagedPool(Block); - } - else if (Block) ExFreeArmPoolWithTag(Block, Tag); - else - { - /* Only warn and break for NULL pointers */ - if (Block == NULL) - { - DPRINT1("Warning: Trying to free a NULL pointer!\n"); - ASSERT(FALSE); - return; - } - - /* Block was not inside any pool! */ - KeBugCheckEx(BAD_POOL_CALLER, 0x42, (ULONG_PTR)Block, 0, 0); - } -} - -/* EOF */ diff --git a/reactos/ntoskrnl/mm/ppool.c b/reactos/ntoskrnl/mm/ppool.c deleted file mode 100644 index 0e3850fb617..00000000000 --- a/reactos/ntoskrnl/mm/ppool.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/ppool.c - * PURPOSE: Implements the paged pool - * - * PROGRAMMERS: David Welch (welch@mcmail.com) - * Royce Mitchell III - */ - -/* INCLUDES *****************************************************************/ - -#include -#define NDEBUG -#include - -#if defined (ALLOC_PRAGMA) -#pragma alloc_text(INIT, MmInitializePagedPool) -#endif - -#undef ASSERT -#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); DbgBreakPoint(); } - -// enable "magic" -//#define R_MAGIC -#define R_MUTEX FAST_MUTEX -#define R_ACQUIRE_MUTEX(pool) /*DPRINT1("Acquiring PPool Mutex\n");*/ ExAcquireFastMutex(&pool->Mutex) -#define R_RELEASE_MUTEX(pool) /*DPRINT1("Releasing PPool Mutex\n");*/ ExReleaseFastMutex(&pool->Mutex) -#define R_PRINT_ADDRESS(addr) KeRosPrintAddress(addr) -#define R_PANIC() KeBugCheck(MEMORY_MANAGEMENT) -#define R_DEBUG DbgPrint - -#ifdef _ARM_ -#define R_GET_STACK_FRAMES(ptr,cnt) -#else -#define R_GET_STACK_FRAMES(ptr,cnt) RtlWalkFrameChain((PVOID*)ptr,cnt, 0) -#endif - -#include "rpoolmgr.h" - -/* GLOBALS *******************************************************************/ - -PVOID MmPagedPoolBase; -ULONG MmPagedPoolSize; -ULONG MmTotalPagedPoolQuota = 0; // TODO FIXME commented out until we use it -static PR_POOL MmPagedPool = NULL; - -/* FUNCTIONS *****************************************************************/ - -VOID -INIT_FUNCTION -NTAPI -MmInitializePagedPool(VOID) -{ - /* - * We are still at a high IRQL level at this point so explicitly commit - * the first page of the paged pool before writing the first block header. - */ - MmCommitPagedPoolAddress ( (PVOID)MmPagedPoolBase, FALSE ); - - MmPagedPool = RPoolInit ( MmPagedPoolBase, - MmPagedPoolSize, - MM_POOL_ALIGNMENT, - MM_CACHE_LINE_SIZE, - PAGE_SIZE ); - - ExInitializeFastMutex(&MmPagedPool->Mutex); -} - -/********************************************************************** - * NAME INTERNAL - * ExAllocatePagedPoolWithTag@12 - * - * DESCRIPTION - * - * ARGUMENTS - * - * RETURN VALUE - */ -PVOID NTAPI -ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType, - IN ULONG NumberOfBytes, - IN ULONG Tag) -{ - int align; - - if ( NumberOfBytes >= PAGE_SIZE ) - align = 2; - else if ( PoolType & CACHE_ALIGNED_POOL_MASK ) - align = 1; - else - align = 0; - - ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); - - return RPoolAlloc ( MmPagedPool, NumberOfBytes, Tag, align ); -} - -VOID NTAPI -ExFreePagedPool(IN PVOID Block) -{ - ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL); - RPoolFree ( MmPagedPool, Block ); -} - -ULONG NTAPI -EiGetPagedPoolTag(IN PVOID Block) -{ - return RBodyToHdr(Block)->Tag; -} - - -#ifdef PPOOL_UMODE_TEST - -PVOID TestAlloc ( ULONG Bytes ) -{ - PVOID ret; - - //printf ( "Allocating block: " ); RPoolStats ( MmPagedPool ); - //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ ); - - ret = ExAllocatePagedPoolWithTag ( PagedPool, Bytes, 0 ); - - //printf ( "Block %x allocated: ", ret ); RPoolStats ( MmPagedPool ); - //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ ); - - return ret; -} - -void TestFree ( PVOID ptr ) -{ - //printf ( "Freeing block %x: ", ptr ); RPoolStats ( MmPagedPool ); - //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ ); - ExFreePagedPool(ptr); - //printf ( "Block %x freed: ", ptr ); RPoolStats ( MmPagedPool ); - //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ ); -} - -int main() -{ -#define COUNT 100 - int i, j; - char* keepers[COUNT]; - char* trash[COUNT]; - int AllocSize[] = { 15, 31, 63, 127, 255, 511, 1023, 2047 }; - const int ALLOCS = sizeof(AllocSize) / sizeof(0[AllocSize]); - ULONG dwStart; - - MmPagedPoolSize = 1*1024*1024; - MmPagedPoolBase = malloc ( MmPagedPoolSize ); - MmInitializePagedPool(); - - dwStart = GetTickCount(); - - printf ( "test #1 phase #1\n" ); - for ( i = 0; i < COUNT; i++ ) - { - //printf ( "keeper %i) ", i ); - keepers[i] = TestAlloc ( AllocSize[i%ALLOCS] ); - if ( !keepers[i] ) printf ( "allocation failed\n" ); - //printf ( "trash %i) ", i ); - trash[i] = TestAlloc ( AllocSize[i%ALLOCS] ); - if ( !trash[i] ) printf ( "allocation failed\n" ); - } - - printf ( "test #1 phase #2\n" ); - for ( i = 0; i < COUNT; i++ ) - { - if ( i == 6 ) - i = i; - //printf ( "%i) ", i ); - TestFree ( trash[i] ); - } - - printf ( "test #1 phase #3\n" ); - for ( i = 0; i < 4; i++ ) - { - //printf ( "%i) ", i ); - keepers[i] = TestAlloc ( 4096 ); - if ( !keepers[i] ) printf ( "allocation failed\n" ); - } - - printf ( "test #1 phase #4\n" ); - for ( i = 0; i < 4; i++ ) - { - //printf ( "%i) ", i ); - TestFree ( keepers[i] ); - } - - printf ( "test #1 phase #5\n" ); - srand(1); - for ( i = 0; i < COUNT; i++ ) - { - //printf ( "%i) ", i ); - trash[i] = TestAlloc ( rand()%1024+1 ); - if ( !trash[i] ) printf ( "allocation failed\n" ); - } - printf ( "test #1 phase #6\n" ); - for ( i = 0; i < 10000; i++ ) - { - TestFree ( trash[i%COUNT] ); - trash[i%COUNT] = TestAlloc ( rand()%1024+1 ); - if ( !trash[i%COUNT] ) printf ( "allocation failed\n" ); - } - printf ( "test #1 phase #7\n" ); - j = 0; - for ( i = 0; i < COUNT; i++ ) - { - if ( trash[i] ) - { - TestFree ( trash[i] ); - ++j; - } - } - printf ( "test #1 phase #8 ( freed %i of %i trash )\n", j, COUNT ); - if ( !TestAlloc ( 2048 ) ) - printf ( "Couldn't allocate 2048 bytes after freeing up a whole bunch of blocks\n" ); - - free ( MmPagedPoolBase ); - - printf ( "test time: %lu\n", GetTickCount() - dwStart ); - - printf ( "test #2\n" ); - - MmPagedPoolSize = 1024; - MmPagedPoolBase = malloc ( MmPagedPoolSize ); - MmInitializePagedPool(); - - TestAlloc ( 512 ); - i = RPoolLargestAllocPossible ( MmPagedPool, 0 ); - if ( !TestAlloc ( i ) ) - { - printf ( "allocating last available block failed\n" ); - } - - free ( MmPagedPoolBase ); - - printf ( "done!\n" ); - return 0; -} -#endif//PPOOL_UMODE_TEST - -/* EOF */ diff --git a/reactos/ntoskrnl/mm/rpoolmgr.h b/reactos/ntoskrnl/mm/rpoolmgr.h deleted file mode 100644 index f72cdb366bf..00000000000 --- a/reactos/ntoskrnl/mm/rpoolmgr.h +++ /dev/null @@ -1,1060 +0,0 @@ -/* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: ntoskrnl/mm/RPoolMgr.h - * PURPOSE: A semi-generic reuseable Pool implementation - * PROGRAMMER: Royce Mitchell III - * UPDATE HISTORY: - */ - -#ifndef RPOOLMGR_H -#define RPOOLMGR_H - -typedef unsigned long rulong; - -#define R_IS_POOL_PTR(pool,ptr) (((void*)(ULONG_PTR)(ptr) >= pool->UserBase) && ((ULONG_PTR)(ptr) < ((ULONG_PTR)pool->UserBase + pool->UserSize))) -#define R_ASSERT_PTR(pool,ptr) ASSERT( R_IS_POOL_PTR(pool,ptr) ) -#define R_ASSERT_SIZE(pool,sz) ASSERT( sz > (sizeof(R_USED)+2*R_RZ) && sz >= sizeof(R_FREE) && sz < pool->UserSize ) - -#ifndef R_ROUND_UP -#define R_ROUND_UP(x,s) ((PVOID)(((ULONG_PTR)(x)+(s)-1) & ~((ULONG_PTR)(s)-1))) -#endif//R_ROUND_UP - -#ifndef R_ROUND_DOWN -#define R_ROUND_DOWN(x,s) ((PVOID)(((ULONG_PTR)(x)) & ~((ULONG_PTR)(s)-1))) -#endif//R_ROUND_DOWN - -#ifndef R_QUEMIN -// R_QUEMIN is the minimum number of entries to keep in a que -#define R_QUEMIN 0 -#endif//R_QUEMIN - -#ifndef R_QUECOUNT -// 16, 32, 64, 128, 256, 512 -#define R_QUECOUNT 6 -#endif//R_QUECOUNT - -#ifndef R_RZ -// R_RZ is the redzone size -#define R_RZ 4 -#endif//R_RZ - -#ifndef R_RZ_LOVALUE -#define R_RZ_LOVALUE 0x87 -#endif//R_RZ_LOVALUE - -#ifndef R_RZ_HIVALUE -#define R_RZ_HIVALUE 0xA5 -#endif//R_RZ_HIVALUE - -#ifndef R_STACK -// R_STACK is the number of stack entries to store in blocks for debug purposes -#define R_STACK 6 -#else // R_STACK -#if R_STACK > 0 && R_STACK < 6 -/* Increase the frame depth to get a reasonable back trace */ -#undef R_STACK -#define R_STACK 6 -#endif // R_STACK > 0 && R_STACK < 6 -#endif//R_STACK - -#ifndef R_TAG -// R_TAG do we keep track of tags on a per-memory block basis? -#define R_TAG 0 -#endif//R_TAG - -#ifdef R_MAGIC -# ifndef R_FREE_MAGIC -# define R_FREE_MAGIC (rulong)(('F'<<0) + ('r'<<8) + ('E'<<16) + ('e'<<24)) -# endif//R_FREE_MAGIC -# ifndef R_USED_MAGIC -# define R_USED_MAGIC (rulong)(('u'<<0) + ('S'<<8) + ('e'<<16) + ('D'<<24)) -# endif//R_USED_MAGIC -#endif//R_MAGIC - -// **IMPORTANT NOTE** Magic, PrevSize, Size and Status must be at same offset -// in both the R_FREE and R_USED structures - -typedef struct _R_FREE -{ -#ifdef R_MAGIC - rulong FreeMagic; -#endif//R_MAGIC - rulong PrevSize : 30; - rulong Status : 2; - rulong Size; -#if R_STACK - ULONG_PTR LastOwnerStack[R_STACK]; -#endif//R_STACK - struct _R_FREE* NextFree; - struct _R_FREE* PrevFree; -} -R_FREE, *PR_FREE; - -typedef struct _R_USED -{ -#ifdef R_MAGIC - rulong UsedMagic; -#endif//R_MAGIC - rulong PrevSize : 30; - rulong Status : 2; - rulong Size; -#if R_STACK - ULONG_PTR LastOwnerStack[R_STACK]; -#endif//R_STACK - struct _R_USED* NextUsed; -#if R_RZ - rulong UserSize; // how many bytes the user actually asked for... -#endif//R_RZ - rulong Tag; -} -R_USED, *PR_USED; - -typedef struct _R_QUE -{ - rulong Count; - PR_USED First, Last; -} -R_QUE, *PR_QUE; - -typedef struct _R_POOL -{ - void* PoolBase; - rulong PoolSize; - void* UserBase; - rulong UserSize; - rulong Alignments[3]; - PR_FREE FirstFree, LastFree; - R_QUE Que[R_QUECOUNT][3]; - R_MUTEX Mutex; -} -R_POOL, *PR_POOL; - -#if !R_STACK -#define RiPrintLastOwner(Block) -#else -static void -RiPrintLastOwner ( PR_USED Block ) -{ - int i; - for ( i = 0; i < R_STACK; i++ ) - { - if ( Block->LastOwnerStack[i] != 0xDEADBEEF ) - { - R_DEBUG(" "); - //if (!R_PRINT_ADDRESS ((PVOID)Block->LastOwnerStack[i]) ) - { - R_DEBUG("<%X>", Block->LastOwnerStack[i] ); - } - } - } -} -#endif//R_STACK - -static int -RQueWhich ( rulong size ) -{ - rulong que, quesize; - for ( que=0, quesize=16; que < R_QUECOUNT; que++, quesize<<=1 ) - { - if ( quesize >= size ) - { - return que; - } - } - return -1; -} - -static void -RQueInit ( PR_QUE que ) -{ - que->Count = 0; - que->First = NULL; - que->Last = NULL; -} - -static void -RQueAdd ( PR_QUE que, PR_USED Item ) -{ - ASSERT(Item); - Item->Status = 2; - Item->NextUsed = NULL; - ++que->Count; - if ( !que->Last ) - { - que->First = que->Last = Item; - return; - } - ASSERT(!que->Last->NextUsed); - que->Last->NextUsed = Item; - que->Last = Item; -} - -static PR_USED -RQueRemove ( PR_QUE que ) -{ - PR_USED Item; -#if R_QUEMIN - if ( que->count < R_QUEMIN ) - return NULL; -#endif - if ( !que->First ) - return NULL; - Item = que->First; - que->First = Item->NextUsed; - if ( !--que->Count ) - { - ASSERT ( !que->First ); - que->Last = NULL; - } - Item->Status = 0; - return Item; -} - -static void -RPoolAddFree ( PR_POOL pool, PR_FREE Item ) -{ - ASSERT(pool); - ASSERT(Item); - if ( !pool->FirstFree ) - { - pool->FirstFree = pool->LastFree = Item; - Item->NextFree = NULL; - } - else - { - pool->FirstFree->PrevFree = Item; - Item->NextFree = pool->FirstFree; - pool->FirstFree = Item; - } - Item->PrevFree = NULL; -} - -static void -RPoolRemoveFree ( PR_POOL pool, PR_FREE Item ) -{ - ASSERT(pool); - ASSERT(Item); - if ( Item->NextFree ) - Item->NextFree->PrevFree = Item->PrevFree; - else - { - ASSERT ( pool->LastFree == Item ); - pool->LastFree = Item->PrevFree; - } - if ( Item->PrevFree ) - Item->PrevFree->NextFree = Item->NextFree; - else - { - ASSERT ( pool->FirstFree == Item ); - pool->FirstFree = Item->NextFree; - } -#if DBG - Item->NextFree = Item->PrevFree = (PR_FREE)(ULONG_PTR)0xDEADBEEF; -#endif//DBG -} - -#if !R_STACK -#define RFreeFillStack(free) -#define RUsedFillStack(used) -#else -static void -RFreeFillStack ( PR_FREE free ) -{ - int i; - ULONG stack[R_STACK+3]; // need to skip 3 known levels of stack trace - memset ( stack, 0xCD, sizeof(stack) ); - R_GET_STACK_FRAMES ( stack, R_STACK+3 ); - for ( i = 0; i < R_STACK; i++ ) - free->LastOwnerStack[i] = stack[i+3]; -} - -static void -RUsedFillStack ( PR_USED used ) -{ - int i; - ULONG stack[R_STACK+2]; // need to skip 2 known levels of stack trace - memset ( stack, 0xCD, sizeof(stack) ); - R_GET_STACK_FRAMES ( stack, R_STACK+2 ); - for ( i = 0; i < R_STACK; i++ ) - used->LastOwnerStack[i] = stack[i+2]; -} -#endif - -static PR_FREE -RFreeInit ( void* memory ) -{ - PR_FREE block = (PR_FREE)memory; -#if R_FREEMAGIC - block->FreeMagic = R_FREE_MAGIC; -#endif//R_FREEMAGIC - block->Status = 0; - RFreeFillStack ( block ); -#if DBG - block->PrevFree = block->NextFree = (PR_FREE)(ULONG_PTR)0xDEADBEEF; -#endif//DBG - return block; -} - -PR_POOL -RPoolInit ( void* PoolBase, rulong PoolSize, int align1, int align2, int align3 ) -{ - int align, que; - PR_POOL pool = (PR_POOL)PoolBase; - - pool->PoolBase = PoolBase; - pool->PoolSize = PoolSize; - pool->UserBase = (char*)pool->PoolBase + sizeof(R_POOL); - pool->UserSize = PoolSize - sizeof(R_POOL); - pool->Alignments[0] = align1; - pool->Alignments[1] = align2; - pool->Alignments[2] = align3; - pool->FirstFree = pool->LastFree = NULL; - - RPoolAddFree ( pool, - RFreeInit ( pool->UserBase )); - - pool->FirstFree->PrevSize = 0; - pool->FirstFree->Size = pool->UserSize; - - for ( que = 0; que < R_QUECOUNT; que++ ) - { - for ( align = 0; align < 3; align++ ) - { - RQueInit ( &pool->Que[que][align] ); - } - } - return pool; -} - -#if R_RZ -static const char* -RFormatTag ( rulong Tag, char* buf ) -{ - int i; - *(rulong*)&buf[0] = Tag; - buf[4] = 0; - for ( i = 0; i < 4; i++ ) - { - if ( !buf[i] ) - buf[i] = ' '; - } - return buf; -} -#endif - -#if !R_RZ -#define RUsedRedZoneCheck(pUsed,Addr,file,line, printzone) -#else//R_RZ -static void -RiBadBlock ( PR_USED pUsed, char* Addr, const char* violation, const char* file, int line, int printzone ) -{ - char tag[5]; - unsigned int i; - - R_DEBUG("%s(%i): %s detected for paged pool address 0x%x\n", - file, line, violation, Addr ); - -#ifdef R_MAGIC - R_DEBUG ( "UsedMagic 0x%x, ", pUsed->UsedMagic ); -#endif//R_MAGIC - R_DEBUG ( "Tag %s(%X), Size %i, UserSize %i", - RFormatTag(pUsed->Tag,tag), - pUsed->Tag, - pUsed->Size, - pUsed->UserSize ); - - if ( printzone ) - { - unsigned char* HiZone = (unsigned char*)Addr + pUsed->UserSize; - unsigned char* LoZone = (unsigned char*)Addr - R_RZ; // this is to simplify indexing below... - R_DEBUG ( ", LoZone " ); - for ( i = 0; i < R_RZ; i++ ) - R_DEBUG ( "%02x", LoZone[i] ); - R_DEBUG ( ", HiZone " ); - for ( i = 0; i < R_RZ; i++ ) - R_DEBUG ( "%02x", HiZone[i] ); - } - R_DEBUG ( "\n" ); - - R_DEBUG ( "First few Stack Frames:" ); - RiPrintLastOwner ( pUsed ); - R_DEBUG ( "\n" ); - - R_DEBUG ( "Contents of Block:\n" ); - for ( i = 0; i < 8*16 && i < pUsed->UserSize; i += 16 ) - { - int j; - R_DEBUG ( "%04X ", i ); - for ( j = 0; j < 16; j++ ) - { - if ( i+j < pUsed->UserSize ) - { - R_DEBUG ( "%02X ", (unsigned)(unsigned char)Addr[i+j] ); - } - else - { - R_DEBUG ( " " ); - } - } - R_DEBUG(" "); - for ( j = 0; j < 16; j++ ) - { - if ( i+j < pUsed->UserSize ) - { - char c = Addr[i+j]; - if ( c < 0x20 || c > 0x7E ) - c = '.'; - R_DEBUG ( "%c", c ); - } - else - { - R_DEBUG ( " " ); - } - } - R_DEBUG("\n"); - } - R_PANIC(); -} -static void -RUsedRedZoneCheck ( PR_POOL pool, PR_USED pUsed, char* Addr, const char* file, int line ) -{ - int i; - unsigned char *LoZone, *HiZone; - int bLow = 1; - int bHigh = 1; - - ASSERT ( Addr >= (char*)pool->UserBase && Addr < ((char*)pool->UserBase + pool->UserSize - 16) ); -#ifdef R_MAGIC - if ( pUsed->UsedMagic == R_FREE_MAGIC ) - { - pUsed->UserSize = 0; // just to keep from confusion, MmpBadBlock() doesn't return... - RiBadBlock ( pUsed, Addr, "double-free", file, line, 0 ); - } - if ( pUsed->UsedMagic != R_USED_MAGIC ) - { - RiBadBlock ( pUsed, Addr, "bad magic", file, line, 0 ); - } -#endif//R_MAGIC - switch ( pUsed->Status ) - { - case 0: // freed into main pool - case 2: // in ques - RiBadBlock ( pUsed, Addr, "double-free", file, line, 0 ); - // no need for break here - RiBadBlock doesn't return - case 1: // allocated - this is okay - break; - default: - RiBadBlock ( pUsed, Addr, "corrupt status", file, line, 0 ); - } - if ( pUsed->Status != 1 ) - { - RiBadBlock ( pUsed, Addr, "double-free", file, line, 0 ); - } - if ( pUsed->Size > pool->PoolSize || pUsed->Size == 0 ) - { - RiBadBlock ( pUsed, Addr, "invalid size", file, line, 0 ); - } - if ( pUsed->UserSize > pool->PoolSize || pUsed->UserSize == 0 ) - { - RiBadBlock ( pUsed, Addr, "invalid user size", file, line, 0 ); - } - HiZone = (unsigned char*)Addr + pUsed->UserSize; - LoZone = (unsigned char*)Addr - R_RZ; // this is to simplify indexing below... - for ( i = 0; i < R_RZ && bLow && bHigh; i++ ) - { - bLow = bLow && ( LoZone[i] == R_RZ_LOVALUE ); - bHigh = bHigh && ( HiZone[i] == R_RZ_HIVALUE ); - } - if ( !bLow || !bHigh ) - { - const char* violation = "High and Low-side redzone overwrite"; - if ( bHigh ) // high is okay, so it was just low failed - violation = "Low-side redzone overwrite"; - else if ( bLow ) // low side is okay, so it was just high failed - violation = "High-side redzone overwrite"; - RiBadBlock ( pUsed, Addr, violation, file, line, 1 ); - } -} -#endif//R_RZ - -PR_FREE -RPreviousBlock ( PR_FREE Block ) -{ - if ( Block->PrevSize > 0 ) - return (PR_FREE)( (char*)Block - Block->PrevSize ); - return NULL; -} - -PR_FREE -RNextBlock ( PR_POOL pool, PR_FREE Block ) -{ - PR_FREE NextBlock = (PR_FREE)( (char*)Block + Block->Size ); - if ( (char*)NextBlock >= (char*)pool->UserBase + pool->UserSize ) - NextBlock = NULL; - return NextBlock; -} - -static __inline void* -RHdrToBody ( void* blk ) -/* - * FUNCTION: Translate a block header address to the corresponding block - * address (internal) - */ -{ - return ( (void *) ((char*)blk + sizeof(R_USED) + R_RZ) ); -} - -static __inline PR_USED -RBodyToHdr ( void* addr ) -{ - return (PR_USED) - ( ((char*)addr) - sizeof(R_USED) - R_RZ ); -} - -static int -RiInFreeChain ( PR_POOL pool, PR_FREE Block ) -{ - PR_FREE Free; - Free = pool->FirstFree; - if ( Free == Block ) - return 1; - while ( Free != Block ) - { - Free = Free->NextFree; - if ( !Free ) - return 0; - } - return 1; -} - -static void -RPoolRedZoneCheck ( PR_POOL pool, const char* file, int line ) -{ - { - PR_USED Block = (PR_USED)pool->UserBase; - PR_USED NextBlock; - - for ( ;; ) - { - switch ( Block->Status ) - { - case 0: // block is in chain - ASSERT ( RiInFreeChain ( pool, (PR_FREE)Block ) ); - break; - case 1: // block is allocated - RUsedRedZoneCheck ( pool, Block, RHdrToBody(Block), file, line ); - break; - case 2: // block is in que - // nothing to verify here yet - break; - default: - ASSERT ( !"invalid status in memory block found in pool!" ); - } - NextBlock = (PR_USED)RNextBlock(pool,(PR_FREE)Block); - if ( !NextBlock ) - break; - ASSERT ( NextBlock->PrevSize == Block->Size ); - Block = NextBlock; - } - } - { - // now let's step through the list of free pointers and verify - // each one can be found by size-jumping... - PR_FREE Free = (PR_FREE)pool->FirstFree; - while ( Free ) - { - PR_FREE NextFree = (PR_FREE)pool->UserBase; - if ( Free != NextFree ) - { - while ( NextFree != Free ) - { - NextFree = RNextBlock ( pool, NextFree ); - ASSERT(NextFree); - } - } - Free = Free->NextFree; - } - } -} - -static void -RSetSize ( PR_POOL pool, PR_FREE Block, rulong NewSize, PR_FREE NextBlock ) -{ - R_ASSERT_PTR(pool,Block); - ASSERT ( NewSize < pool->UserSize ); - ASSERT ( NewSize >= sizeof(R_FREE) ); - Block->Size = NewSize; - if ( !NextBlock ) - NextBlock = RNextBlock ( pool, Block ); - if ( NextBlock ) - NextBlock->PrevSize = NewSize; -} - -static PR_FREE -RFreeSplit ( PR_POOL pool, PR_FREE Block, rulong NewSize ) -{ - PR_FREE NewBlock = (PR_FREE)((char*)Block + NewSize); - RSetSize ( pool, NewBlock, Block->Size - NewSize, NULL ); - RSetSize ( pool, Block, NewSize, NewBlock ); - RFreeInit ( NewBlock ); - RPoolAddFree ( pool, NewBlock ); - return NewBlock; -} - -static void -RFreeMerge ( PR_POOL pool, PR_FREE First, PR_FREE Second ) -{ - ASSERT ( RPreviousBlock(Second) == First ); - ASSERT ( First->Size == Second->PrevSize ); - RPoolRemoveFree ( pool, Second ); - RSetSize ( pool, First, First->Size + Second->Size, NULL ); -} - -static void -RPoolReclaim ( PR_POOL pool, PR_FREE FreeBlock ) -{ - PR_FREE NextBlock, PreviousBlock; - - RFreeInit ( FreeBlock ); - RPoolAddFree ( pool, FreeBlock ); - - // TODO FIXME - don't merge and always insert freed blocks at the end for debugging purposes... - - /* - * If the next block is immediately adjacent to the newly freed one then - * merge them. - * PLEASE DO NOT WIPE OUT 'MAGIC' OR 'LASTOWNER' DATA FOR MERGED FREE BLOCKS - */ - NextBlock = RNextBlock ( pool, FreeBlock ); - if ( NextBlock != NULL && !NextBlock->Status ) - { - RFreeMerge ( pool, FreeBlock, NextBlock ); - } - - /* - * If the previous block is adjacent to the newly freed one then - * merge them. - * PLEASE DO NOT WIPE OUT 'MAGIC' OR 'LASTOWNER' DATA FOR MERGED FREE BLOCKS - */ - PreviousBlock = RPreviousBlock ( FreeBlock ); - if ( PreviousBlock != NULL && !PreviousBlock->Status ) - { - RFreeMerge ( pool, PreviousBlock, FreeBlock ); - } -} - -static void -RiUsedInit ( PR_USED Block, rulong Tag ) -{ - Block->Status = 1; - RUsedFillStack ( Block ); -#ifdef R_MAGIC - Block->UsedMagic = R_USED_MAGIC; -#endif//R_MAGIC - //ASSERT_SIZE ( Block->Size ); - - // now add the block to the used block list -#if DBG - Block->NextUsed = (PR_USED)(ULONG_PTR)0xDEADBEEF; -#endif//R_USED_LIST - - Block->Tag = Tag; -} - -#if !R_RZ -#define RiUsedInitRedZone(Block,UserSize) -#else//R_RZ -static void -RiUsedInitRedZone ( PR_USED Block, rulong UserSize ) -{ - // write out buffer-overrun detection bytes - char* Addr = (char*)RHdrToBody(Block); - Block->UserSize = UserSize; - memset ( Addr - R_RZ, R_RZ_LOVALUE, R_RZ ); - memset ( Addr + Block->UserSize, R_RZ_HIVALUE, R_RZ ); -#if DBG - memset ( Addr, 0xCD, UserSize ); -#endif//DBG -} -#endif//R_RZ - -static void* -RPoolAlloc ( PR_POOL pool, rulong NumberOfBytes, rulong Tag, rulong align ) -{ - PR_USED NewBlock; - PR_FREE BestBlock, - NextBlock, - PreviousBlock, - BestPreviousBlock, - CurrentBlock; - void* BestAlignedAddr; - int que, - queBytes = NumberOfBytes; - rulong BlockSize, - Alignment; - int que_reclaimed = 0; - - ASSERT ( pool ); - ASSERT ( align < 3 ); - - R_ACQUIRE_MUTEX(pool); - - if ( !NumberOfBytes ) - { - R_DEBUG("0 bytes requested - initiating pool verification\n"); - RPoolRedZoneCheck ( pool, __FILE__, __LINE__ ); - R_RELEASE_MUTEX(pool); - return NULL; - } - if ( NumberOfBytes > pool->PoolSize ) - { - if ( R_IS_POOL_PTR(pool,NumberOfBytes) ) - { - R_DEBUG("red zone verification requested for block 0x%X\n", NumberOfBytes ); - RUsedRedZoneCheck(pool,RBodyToHdr((void*)(ULONG_PTR)NumberOfBytes), (char*)(ULONG_PTR)NumberOfBytes, __FILE__, __LINE__ ); - R_RELEASE_MUTEX(pool); - return NULL; - } - R_DEBUG("Invalid allocation request: %i bytes\n", NumberOfBytes ); - R_RELEASE_MUTEX(pool); - return NULL; - } - - que = RQueWhich ( NumberOfBytes ); - if ( que >= 0 ) - { - if ( (NewBlock = RQueRemove ( &pool->Que[que][align] )) ) - { - RiUsedInit ( NewBlock, Tag ); - RiUsedInitRedZone ( NewBlock, NumberOfBytes ); - R_RELEASE_MUTEX(pool); - return RHdrToBody(NewBlock); - } - queBytes = 16 << que; - } - - /* - * Calculate the total number of bytes we will need. - */ - BlockSize = queBytes + sizeof(R_USED) + 2*R_RZ; - if (BlockSize < sizeof(R_FREE)) - { - /* At least we need the size of the free block header. */ - BlockSize = sizeof(R_FREE); - } - -try_again: - /* - * Find the best-fitting block. - */ - BestBlock = NULL; - Alignment = pool->Alignments[align]; - PreviousBlock = NULL; - BestPreviousBlock = NULL, - CurrentBlock = pool->FirstFree; - BestAlignedAddr = NULL; - - while ( CurrentBlock != NULL ) - { - PVOID Addr = RHdrToBody(CurrentBlock); - PVOID CurrentBlockEnd = (char*)CurrentBlock + CurrentBlock->Size; - /* calculate last size-aligned address available within this block */ - PVOID AlignedAddr = R_ROUND_DOWN((char*)CurrentBlockEnd-queBytes-R_RZ, Alignment); - ASSERT ( (char*)AlignedAddr+queBytes+R_RZ <= (char*)CurrentBlockEnd ); - - /* special case, this address is already size-aligned, and the right size */ - if ( Addr == AlignedAddr ) - { - BestAlignedAddr = AlignedAddr; - BestPreviousBlock = PreviousBlock; - BestBlock = CurrentBlock; - break; - } - // if we carve out a size-aligned block... is it still past the end of this - // block's free header? - else if ( (char*)RBodyToHdr(AlignedAddr) - >= (char*)CurrentBlock+sizeof(R_FREE) ) - { - /* - * there's enough room to allocate our size-aligned memory out - * of this block, see if it's a better choice than any previous - * finds - */ - if ( BestBlock == NULL - || BestBlock->Size > CurrentBlock->Size ) - { - BestAlignedAddr = AlignedAddr; - BestPreviousBlock = PreviousBlock; - BestBlock = CurrentBlock; - } - } - - PreviousBlock = CurrentBlock; - CurrentBlock = CurrentBlock->NextFree; - } - - /* - * We didn't find anything suitable at all. - */ - if (BestBlock == NULL) - { - if ( !que_reclaimed ) - { - // reclaim que - int i, j; - for ( i = 0; i < R_QUECOUNT; i++ ) - { - for ( j = 0; j < 3; j++ ) - { - while ( (BestBlock = (PR_FREE)RQueRemove ( &pool->Que[i][j] )) ) - { - RPoolReclaim ( pool, BestBlock ); - } - } - } - - que_reclaimed = 1; - goto try_again; - } - DPRINT1("Trying to allocate %lu bytes from paged pool - nothing suitable found, returning NULL\n", - queBytes ); - R_RELEASE_MUTEX(pool); - return NULL; - } - /* - * we found a best block. If Addr isn't already aligned, we've pre-qualified that - * there's room at the beginning of the block for a free block... - */ - { - void* Addr = RHdrToBody(BestBlock); - if ( BestAlignedAddr != Addr ) - { - PR_FREE NewFreeBlock = RFreeSplit ( - pool, - BestBlock, - (char*)RBodyToHdr(BestAlignedAddr) - (char*)BestBlock ); - ASSERT ( BestAlignedAddr > Addr ); - - //DPRINT ( "breaking off preceding bytes into their own block...\n" ); - /*DPRINT ( "NewFreeBlock 0x%x Size %lu (Old Block's new size %lu) NextFree 0x%x\n", - NewFreeBlock, NewFreeBlock->Size, BestBlock->Size, BestBlock->NextFree );*/ - - /* we want the following code to use our size-aligned block */ - BestPreviousBlock = BestBlock; - BestBlock = NewFreeBlock; - - //VerifyPagedPool(); - } - } - /* - * Is there enough space to create a second block from the unused portion. - */ - if ( (BestBlock->Size - BlockSize) > sizeof(R_FREE) ) - { - /*DPRINT("BestBlock 0x%x Size 0x%x BlockSize 0x%x NewSize 0x%x\n", - BestBlock, BestBlock->Size, BlockSize, NewSize );*/ - - /* - * Create the new free block. - */ - NextBlock = RFreeSplit ( pool, BestBlock, BlockSize ); - //ASSERT_SIZE ( NextBlock->Size ); - } - /* - * Remove the selected block from the list of free blocks. - */ - //DPRINT ( "Removing selected block from free block list\n" ); - RPoolRemoveFree ( pool, BestBlock ); - /* - * Create the new used block header. - */ - NewBlock = (PR_USED)BestBlock; - RiUsedInit ( NewBlock, Tag ); - - /* RtlZeroMemory(RHdrToBody(NewBlock), NumberOfBytes);*/ - - RiUsedInitRedZone ( NewBlock, NumberOfBytes ); - R_RELEASE_MUTEX(pool); - - return RHdrToBody(NewBlock); -} - -static void -RPoolFree ( PR_POOL pool, void* Addr ) -{ - PR_USED UsedBlock; - rulong UsedSize; - PR_FREE FreeBlock; - rulong UserSize; - int que; - - ASSERT(pool); - if ( !Addr ) - { - R_DEBUG("Attempt to free NULL ptr, initiating Red Zone Check\n" ); - R_ACQUIRE_MUTEX(pool); - RPoolRedZoneCheck ( pool, __FILE__, __LINE__ ); - R_RELEASE_MUTEX(pool); - return; - } - R_ASSERT_PTR(pool,Addr); - - UsedBlock = RBodyToHdr(Addr); - UsedSize = UsedBlock->Size; - FreeBlock = (PR_FREE)UsedBlock; -#if R_RZ - UserSize = UsedBlock->UserSize; -#else - UserSize = UsedSize - sizeof(R_USED) - 2*R_RZ; -#endif//R_RZ - - RUsedRedZoneCheck ( pool, UsedBlock, Addr, __FILE__, __LINE__ ); - -#if R_RZ - memset ( Addr, 0xCD, UsedBlock->UserSize ); -#endif - - que = RQueWhich ( UserSize ); - if ( que >= 0 ) - { - int queBytes = 16 << que; - ASSERT( (rulong)queBytes >= UserSize ); - if ( que >= 0 ) - { - int align = 0; - if ( R_ROUND_UP(Addr,pool->Alignments[2]) == Addr ) - align = 2; - else if ( R_ROUND_UP(Addr,pool->Alignments[1]) == Addr ) - align = 1; - R_ACQUIRE_MUTEX(pool); - RQueAdd ( &pool->Que[que][align], UsedBlock ); - R_RELEASE_MUTEX(pool); - return; - } - } - - R_ACQUIRE_MUTEX(pool); - RPoolReclaim ( pool, FreeBlock ); - R_RELEASE_MUTEX(pool); -} - -#if 0 -static void -RPoolDumpByTag ( PR_POOL pool, rulong Tag ) -{ - PR_USED Block = (PR_USED)pool->UserBase; - PR_USED NextBlock; - int count = 0; - char tag[5]; - - // TODO FIXME - should we validate params or ASSERT_IRQL? - R_DEBUG ( "PagedPool Dump by tag '%s'\n", RFormatTag(Tag,tag) ); - R_DEBUG ( " -BLOCK-- --SIZE--\n" ); - - R_ACQUIRE_MUTEX(pool); - for ( ;; ) - { - if ( Block->Status == 1 && Block->Tag == Tag ) - { - R_DEBUG ( " %08X %08X\n", Block, Block->Size ); - ++count; - } - NextBlock = (PR_USED)RNextBlock(pool,(PR_FREE)Block); - if ( !NextBlock ) - break; - ASSERT ( NextBlock->PrevSize == Block->Size ); - Block = NextBlock; - } - R_RELEASE_MUTEX(pool); - - R_DEBUG ( "Entries found for tag '%s': %i\n", tag, count ); -} -#endif - -rulong -RPoolQueryTag ( void* Addr ) -{ - PR_USED Block = RBodyToHdr(Addr); - // TODO FIXME - should we validate params? -#ifdef R_MAGIC - if ( Block->UsedMagic != R_USED_MAGIC ) - return 0xDEADBEEF; -#endif//R_MAGIC - if ( Block->Status != 1 ) - return 0xDEADBEEF; - return Block->Tag; -} - -void -RPoolStats ( PR_POOL pool ) -{ - int free=0, used=0, qued=0; - PR_USED Block = (PR_USED)pool->UserBase; - - R_ACQUIRE_MUTEX(pool); - while ( Block ) - { - switch ( Block->Status ) - { - case 0: - ++free; - break; - case 1: - ++used; - break; - case 2: - ++qued; - break; - default: - ASSERT ( !"Invalid Status for Block in pool!" ); - } - Block = (PR_USED)RNextBlock(pool,(PR_FREE)Block); - } - R_RELEASE_MUTEX(pool); - - R_DEBUG ( "Pool Stats: Free=%i, Used=%i, Qued=%i, Total=%i\n", free, used, qued, (free+used+qued) ); -} - -#ifdef R_LARGEST_ALLOC_POSSIBLE -static rulong -RPoolLargestAllocPossible ( PR_POOL pool, int align ) -{ - int Alignment = pool->Alignments[align]; - rulong LargestUserSize = 0; - PR_FREE Block = (PR_FREE)pool->UserBase; - while ( Block ) - { - if ( Block->Status != 1 ) - { - void* Addr, *AlignedAddr; - rulong BlockMaxUserSize; - int cue, cueBytes; - - Addr = (char*)Block + sizeof(R_USED) + R_RZ; - AlignedAddr = R_ROUND_UP(Addr,Alignment); - if ( Addr != AlignedAddr ) - Addr = R_ROUND_UP((char*)Block + sizeof(R_FREE) + sizeof(R_USED) + R_RZ, Alignment ); - BlockMaxUserSize = (char*)Block + Block->Size - (char*)Addr - R_RZ; - cue = RQueWhich ( BlockMaxUserSize ); - if ( cue >= 0 ) - { - cueBytes = 16 << cue; - if ( cueBytes > BlockMaxUserSize ); - { - if ( !cue ) - BlockMaxUserSize = 0; - else - BlockMaxUserSize = 16 << (cue-1); - } - } - if ( BlockMaxUserSize > LargestUserSize ) - LargestUserSize = BlockMaxUserSize; - } - Block = RNextBlock ( pool, Block ); - } - return LargestUserSize; -} -#endif//R_LARGEST_ALLOC_POSSIBLE - -#endif//RPOOLMGR_H diff --git a/reactos/ntoskrnl/ntoskrnl-generic.rbuild b/reactos/ntoskrnl/ntoskrnl-generic.rbuild index e5782b1fab8..b20bf9b6a76 100644 --- a/reactos/ntoskrnl/ntoskrnl-generic.rbuild +++ b/reactos/ntoskrnl/ntoskrnl-generic.rbuild @@ -403,7 +403,6 @@ anonmem.c balance.c - dbgpool.c freelist.c marea.c @@ -415,8 +414,6 @@ pagefile.c pageop.c pe.c - pool.c - ppool.c procsup.c region.c rmap.c