-/* $Id: ppool.c,v 1.20 2003/10/12 17:05:48 hbirr Exp $
+/* $Id: ppool.c,v 1.37 2004/12/17 13:20:05 royce Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* PROGRAMMER: David Welch (welch@mcmail.com)
* UPDATE HISTORY:
* Created 22/05/98
+ * Complete Rewrite Dec 2004 by Royce Mitchell III
*/
/* INCLUDES *****************************************************************/
-#include <ddk/ntddk.h>
-#include <internal/pool.h>
-#include <internal/mm.h>
-
+#ifdef PPOOL_UMODE_TEST
+#include "ppool_umode.h"
+#else//PPOOL_UMODE_TEST
+#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
+#endif//PPOOL_UMODE_TEST
-/* GLOBALS *******************************************************************/
-
-/* Enable strict checking of the paged pool on every allocation */
-#define ENABLE_VALIDATE_POOL
-
-#undef assert
-#define assert(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
-#define ASSERT_SIZE(n) assert ( (n) <= MmPagedPoolSize && (n) >= 0 )
-#define ASSERT_PTR(p) assert ( ((size_t)(p)) >= ((size_t)MmPagedPoolBase) && ((size_t)(p)) < ((size_t)(MmPagedPoolBase+MmPagedPoolSize)) )
+#undef ASSERT
+#define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
-// to disable buffer over/under-run detection, set the following macro to 0
-#define MM_PPOOL_REDZONE_BYTES 4
-#define MM_PPOOL_REDZONE_VALUE 0xCD
+// 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) 0
+#define R_PANIC() KeBugCheck(0)
+#define R_DEBUG DbgPrint
+#define R_EXTRA_STACK_UP 2
-typedef struct _MM_PPOOL_FREE_BLOCK_HEADER
-{
- ULONG Size;
- struct _MM_PPOOL_FREE_BLOCK_HEADER* NextFree;
-} MM_PPOOL_FREE_BLOCK_HEADER, *PMM_PPOOL_FREE_BLOCK_HEADER;
+#include "RPoolMgr.h"
-typedef struct _MM_PPOOL_USED_BLOCK_HEADER
-{
- ULONG Size;
-#if MM_PPOOL_REDZONE_BYTES
- ULONG UserSize; // how many bytes the user actually asked for...
- struct _MM_PPOOL_USED_BLOCK_HEADER* NextUsed;
-#endif//MM_PPOOL_REDZONE_BYTES
-} MM_PPOOL_USED_BLOCK_HEADER, *PMM_PPOOL_USED_BLOCK_HEADER;
+/* GLOBALS *******************************************************************/
PVOID MmPagedPoolBase;
ULONG MmPagedPoolSize;
-static FAST_MUTEX MmPagedPoolLock;
-static PMM_PPOOL_FREE_BLOCK_HEADER MmPagedPoolFirstFreeBlock;
-#if MM_PPOOL_REDZONE_BYTES
-static PMM_PPOOL_USED_BLOCK_HEADER MmPagedPoolFirstUsedBlock;
-#endif//MM_PPOOL_REDZONE_BYTES
+ULONG MmTotalPagedPoolQuota = 0; // TODO FIXME commented out until we use it
+static PR_POOL MmPagedPool = NULL;
/* FUNCTIONS *****************************************************************/
-inline static void* block_to_address ( PVOID blk )
-/*
- * FUNCTION: Translate a block header address to the corresponding block
- * address (internal)
+VOID INIT_FUNCTION
+MmInitializePagedPool()
+{
+ /*
+ * 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 STDCALL
+ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
+ IN ULONG NumberOfBytes,
+ IN ULONG Tag)
{
- return ( (void *) ((char*)blk + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + MM_PPOOL_REDZONE_BYTES) );
+ int align;
+
+ if ( NumberOfBytes >= PAGE_SIZE )
+ align = 2;
+ else if ( PoolType == PagedPoolCacheAligned )
+ align = 1;
+ else
+ align = 0;
+
+ ASSERT_IRQL(APC_LEVEL);
+
+ return RPoolAlloc ( MmPagedPool, NumberOfBytes, Tag, align );
}
-inline static PMM_PPOOL_USED_BLOCK_HEADER address_to_block(PVOID addr)
+VOID STDCALL
+ExFreePagedPool(IN PVOID Block)
{
- return (PMM_PPOOL_USED_BLOCK_HEADER)
- ( ((char*)addr) - sizeof(MM_PPOOL_USED_BLOCK_HEADER) - MM_PPOOL_REDZONE_BYTES );
+ ASSERT_IRQL(APC_LEVEL);
+ RPoolFree ( MmPagedPool, Block );
}
-VOID INIT_FUNCTION
-MmInitializePagedPool(VOID)
+VOID STDCALL
+ExRosDumpPagedPoolByTag ( ULONG Tag )
{
- MmPagedPoolFirstFreeBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)MmPagedPoolBase;
- /*
- * 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)MmPagedPoolFirstFreeBlock);
- MmPagedPoolFirstFreeBlock->Size = MmPagedPoolSize;
- MmPagedPoolFirstFreeBlock->NextFree = NULL;
-
-#if MM_PPOOL_REDZONE_BYTES
- MmPagedPoolFirstUsedBlock = NULL;
-#endif//MM_PPOOL_REDZONE_BYTES
-
- ExInitializeFastMutex(&MmPagedPoolLock);
+ // TODO FIXME - should we ASSERT_IRQL?
+ RPoolDumpByTag ( MmPagedPool, Tag );
}
-#ifdef ENABLE_VALIDATE_POOL
-static void VerifyPagedPool ( int line )
+ULONG STDCALL
+ExRosQueryPagedPoolTag ( PVOID Addr )
{
- PMM_PPOOL_FREE_BLOCK_HEADER p = MmPagedPoolFirstFreeBlock;
- int count = 0;
- DPRINT ( "VerifyPagedPool(%i):\n", line );
- while ( p )
- {
- DPRINT ( " 0x%x: %lu bytes (next 0x%x)\n", p, p->Size, p->NextFree );
- ASSERT_PTR(p);
- ASSERT_SIZE(p->Size);
- count++;
- p = p->NextFree;
- }
- DPRINT ( "VerifyPagedPool(%i): (%lu blocks)\n", line, count );
+ // TODO FIXME - should we ASSERT_IRQL?
+ return RPoolQueryTag ( Addr );
}
-#define VerifyPagedPool() VerifyPagedPool(__LINE__)
-#else
-#define VerifyPagedPool()
-#endif
-VOID STDCALL
-MmDbgPagedPoolRedZoneCheck ( const char* file, int line )
+#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 )
{
-#if MM_PPOOL_REDZONE_BYTES
- PMM_PPOOL_USED_BLOCK_HEADER pUsed = MmPagedPoolFirstUsedBlock;
- int i;
- BOOL bLow = TRUE;
- BOOL bHigh = TRUE;
-
- while ( pUsed )
- {
- PUCHAR Addr = (PUCHAR)block_to_address(pUsed);
- for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
- {
- bLow = bLow && ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
- bHigh = bHigh && ( *(Addr+pUsed->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
- }
- if ( !bLow || !bHigh )
- {
- const char* violation = "High and Low-side";
- if ( bHigh ) // high is okay, so it was just low failed
- violation = "Low-side";
- else if ( bLow ) // low side is okay, so it was just high failed
- violation = "High-side";
- DbgPrint("%s(%i): %s redzone violation detected for paged pool address 0x%x\n",
- file, line, violation, Addr );
- KEBUGCHECK(0);
- }
- pUsed = pUsed->NextUsed;
- }
-#endif//MM_PPOOL_REDZONE_BYTES
+ //printf ( "Freeing block %x: ", ptr ); RPoolStats ( MmPagedPool );
+ //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
+ ExFreePagedPool(ptr);
+ //printf ( "Block %x freed: ", ptr ); RPoolStats ( MmPagedPool );
+ //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
}
-/**********************************************************************
- * NAME INTERNAL
- * ExAllocatePagedPoolWithTag@12
- *
- * DESCRIPTION
- *
- * ARGUMENTS
- *
- * RETURN VALUE
- */
-PVOID STDCALL
-ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
- IN ULONG NumberOfBytes,
- IN ULONG Tag)
+int main()
{
- PMM_PPOOL_FREE_BLOCK_HEADER BestBlock;
- PMM_PPOOL_FREE_BLOCK_HEADER CurrentBlock;
- ULONG BlockSize;
- PMM_PPOOL_USED_BLOCK_HEADER NewBlock;
- PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
- PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
- PMM_PPOOL_FREE_BLOCK_HEADER BestPreviousBlock;
- PVOID BlockAddress;
- ULONG Alignment;
-
- ExAcquireFastMutex(&MmPagedPoolLock);
-
- /*
- * Don't bother allocating anything for a zero-byte block.
- */
- if (NumberOfBytes == 0)
- {
- MmDbgPagedPoolRedZoneCheck(__FILE__,__LINE__);
- ExReleaseFastMutex(&MmPagedPoolLock);
- return(NULL);
- }
-
- DPRINT ( "ExAllocatePagedPoolWithTag(%i,%lu,%lu)\n", PoolType, NumberOfBytes, Tag );
- VerifyPagedPool();
-
- if (NumberOfBytes >= PAGE_SIZE)
- {
- Alignment = PAGE_SIZE;
- }
- else if (PoolType == PagedPoolCacheAligned)
- {
- Alignment = MM_CACHE_LINE_SIZE;
- }
- else
- {
- Alignment = 0;
- }
-
- /*
- * Calculate the total number of bytes we will need.
- */
- BlockSize = NumberOfBytes + sizeof(MM_PPOOL_USED_BLOCK_HEADER) + 2*MM_PPOOL_REDZONE_BYTES;
- if (BlockSize < sizeof(MM_PPOOL_FREE_BLOCK_HEADER))
- {
- /* At least we need the size of the free block header. */
- BlockSize = sizeof(MM_PPOOL_FREE_BLOCK_HEADER);
- }
-
-
- /*
- * Find the best-fitting block.
- */
- PreviousBlock = NULL;
- BestPreviousBlock = BestBlock = NULL;
- CurrentBlock = MmPagedPoolFirstFreeBlock;
- if ( Alignment > 0 )
- {
- PVOID BestAlignedAddr = NULL;
- while ( CurrentBlock != NULL )
+#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]);
+ DWORD dwStart;
+
+ MmPagedPoolSize = 1*1024*1024;
+ MmPagedPoolBase = malloc ( MmPagedPoolSize );
+ MmInitializePagedPool();
+
+ dwStart = GetTickCount();
+
+ printf ( "test #1 phase #1\n" );
+ for ( i = 0; i < COUNT; i++ )
{
- PVOID Addr = block_to_address(CurrentBlock);
- PVOID CurrentBlockEnd = (PVOID)CurrentBlock + CurrentBlock->Size;
- /* calculate last size-aligned address available within this block */
- PVOID AlignedAddr = MM_ROUND_DOWN(CurrentBlockEnd-NumberOfBytes-MM_PPOOL_REDZONE_BYTES, Alignment);
- assert ( AlignedAddr+NumberOfBytes+MM_PPOOL_REDZONE_BYTES <= CurrentBlockEnd );
-
- /* special case, this address is already size-aligned, and the right size */
- if ( Addr == AlignedAddr )
- {
- BestAlignedAddr = AlignedAddr;
- BestPreviousBlock = PreviousBlock;
- BestBlock = CurrentBlock;
- break;
- }
- else if ( Addr < (PVOID)address_to_block(AlignedAddr) )
- {
- /*
- * 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;
- }
- }
+ //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" );
+ }
- PreviousBlock = CurrentBlock;
- CurrentBlock = CurrentBlock->NextFree;
+ printf ( "test #1 phase #2\n" );
+ for ( i = 0; i < COUNT; i++ )
+ {
+ if ( i == 6 )
+ i = i;
+ //printf ( "%i) ", i );
+ TestFree ( trash[i] );
}
- /*
- * we found a best block can/should we chop a few bytes off the beginning
- * into a separate memory block?
- */
- if ( BestBlock != NULL )
+ printf ( "test #1 phase #3\n" );
+ for ( i = 0; i < 4; i++ )
{
- PVOID Addr = block_to_address(BestBlock);
- if ( BestAlignedAddr != Addr )
- {
- PMM_PPOOL_FREE_BLOCK_HEADER NewFreeBlock =
- (PMM_PPOOL_FREE_BLOCK_HEADER)address_to_block(BestAlignedAddr);
- assert ( BestAlignedAddr > Addr );
- NewFreeBlock->Size = Addr + BestBlock->Size - BestAlignedAddr;
- ASSERT_SIZE(NewFreeBlock->Size);
- BestBlock->Size = (size_t)NewFreeBlock - (size_t)Addr;
- ASSERT_SIZE(BestBlock->Size);
-
- 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 );
-
- /* insert the new block into the chain */
- NewFreeBlock->NextFree = BestBlock->NextFree;
- BestBlock->NextFree = NewFreeBlock;
-
- /* we want the following code to use our size-aligned block */
- BestPreviousBlock = BestBlock;
- BestBlock = NewFreeBlock;
-
- //VerifyPagedPool();
- }
+ //printf ( "%i) ", i );
+ keepers[i] = TestAlloc ( 4096 );
+ if ( !keepers[i] ) printf ( "allocation failed\n" );
}
- }
- /*
- * non-size-aligned block search
- */
- else while ( CurrentBlock != NULL )
- {
- if ( CurrentBlock->Size >= BlockSize
- && ( BestBlock == NULL || BestBlock->Size > CurrentBlock->Size )
- )
+
+ printf ( "test #1 phase #4\n" );
+ for ( i = 0; i < 4; i++ )
{
- BestPreviousBlock = PreviousBlock;
- BestBlock = CurrentBlock;
+ //printf ( "%i) ", i );
+ TestFree ( keepers[i] );
}
- PreviousBlock = CurrentBlock;
- CurrentBlock = CurrentBlock->NextFree;
- }
-
- /*
- * We didn't find anything suitable at all.
- */
- if (BestBlock == NULL)
- {
- DPRINT("ExAllocatePagedPoolWithTag() - nothing suitable found, returning NULL\n" );
- ExReleaseFastMutex(&MmPagedPoolLock);
- return(NULL);
- }
-
- DPRINT("BestBlock 0x%x NextFree 0x%x\n", BestBlock, BestBlock->NextFree );
-
- //VerifyPagedPool();
-
- /*
- * Is there enough space to create a second block from the unused portion.
- */
- if ( BestBlock->Size > BlockSize
- && (BestBlock->Size - BlockSize) > sizeof(MM_PPOOL_FREE_BLOCK_HEADER)
- )
- {
- ULONG NewSize = BestBlock->Size - BlockSize;
- ASSERT_SIZE ( NewSize );
-
- //DPRINT("creating 2nd block from unused portion\n");
- DPRINT("BestBlock 0x%x Size 0x%x BlockSize 0x%x NewSize 0x%x\n",
- BestBlock, BestBlock->Size, BlockSize, NewSize );
-
- /*
- * Create the new free block.
- */
- //DPRINT("creating the new free block");
- NextBlock = (PMM_PPOOL_FREE_BLOCK_HEADER)((char*)BestBlock + BlockSize);
- //DPRINT(".");
- NextBlock->Size = NewSize;
- ASSERT_SIZE ( NextBlock->Size );
- //DPRINT(".");
- NextBlock->NextFree = BestBlock->NextFree;
- //DPRINT(".\n");
-
- /*
- * Replace the old free block with it.
- */
- //DPRINT("replacing old free block with it");
- if (BestPreviousBlock == NULL)
+ printf ( "test #1 phase #5\n" );
+ srand(1);
+ for ( i = 0; i < COUNT; i++ )
{
- //DPRINT("(from beginning)");
- MmPagedPoolFirstFreeBlock = NextBlock;
+ //printf ( "%i) ", i );
+ trash[i] = TestAlloc ( rand()%1024+1 );
+ if ( !trash[i] ) printf ( "allocation failed\n" );
}
- else
+ printf ( "test #1 phase #6\n" );
+ for ( i = 0; i < 10000; i++ )
{
- //DPRINT("(from previous)");
- BestPreviousBlock->NextFree = NextBlock;
+ TestFree ( trash[i%COUNT] );
+ trash[i%COUNT] = TestAlloc ( rand()%1024+1 );
+ if ( !trash[i%COUNT] ) printf ( "allocation failed\n" );
}
- //DPRINT(".\n");
-
- /*
- * Create the new used block header.
- */
- //DPRINT("create new used block header");
- NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock;
- //DPRINT(".");
- NewBlock->Size = BlockSize;
- ASSERT_SIZE ( NewBlock->Size );
- //DPRINT(".\n");
- }
- else
- {
- ULONG NewSize = BestBlock->Size;
-
- /*
- * Remove the selected block from the list of free blocks.
- */
- //DPRINT ( "Removing selected block from free block list\n" );
- if (BestPreviousBlock == NULL)
+ printf ( "test #1 phase #7\n" );
+ j = 0;
+ for ( i = 0; i < COUNT; i++ )
{
- MmPagedPoolFirstFreeBlock = BestBlock->NextFree;
+ if ( trash[i] )
+ {
+ TestFree ( trash[i] );
+ ++j;
+ }
}
- else
+ 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 ) )
{
- BestPreviousBlock->NextFree = BestBlock->NextFree;
+ printf ( "allocating last available block failed\n" );
}
- /*
- * Set up the header of the new block
- */
- NewBlock = (PMM_PPOOL_USED_BLOCK_HEADER)BestBlock;
- NewBlock->Size = NewSize;
- ASSERT_SIZE ( NewBlock->Size );
- }
-
-#if MM_PPOOL_REDZONE_BYTES
- // now add the block to the used block list
- NewBlock->NextUsed = MmPagedPoolFirstUsedBlock;
- MmPagedPoolFirstUsedBlock = NewBlock;
-#endif//MM_PPOOL_REDZONE_BYTES
-
- VerifyPagedPool();
-
- ExReleaseFastMutex(&MmPagedPoolLock);
-
- BlockAddress = block_to_address ( NewBlock );
-
- memset(BlockAddress, 0, NumberOfBytes);
-
-#if MM_PPOOL_REDZONE_BYTES
- NewBlock->UserSize = NumberOfBytes;
- // write out buffer-overrun detection bytes
- {
- PUCHAR Addr = (PUCHAR)BlockAddress;
- //DbgPrint ( "writing buffer-overrun detection bytes" );
- memset ( Addr - MM_PPOOL_REDZONE_BYTES,
- MM_PPOOL_REDZONE_VALUE, MM_PPOOL_REDZONE_BYTES );
- memset ( Addr + NewBlock->UserSize, MM_PPOOL_REDZONE_VALUE,
- MM_PPOOL_REDZONE_BYTES );
- /*for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
- {
- //DbgPrint(".");
- *(Addr-i-1) = 0xCD;
- //DbgPrint("o");
- *(Addr+NewBlock->UserSize+i) = 0xCD;
- }*/
- //DbgPrint ( "done!\n" );
- }
-
-#endif//MM_PPOOL_REDZONE_BYTES
-
- return(BlockAddress);
-}
+ free ( MmPagedPoolBase );
-VOID STDCALL
-ExFreePagedPool(IN PVOID Block)
-{
- PMM_PPOOL_FREE_BLOCK_HEADER PreviousBlock;
- PMM_PPOOL_USED_BLOCK_HEADER UsedBlock = address_to_block(Block);
- ULONG UsedSize = UsedBlock->Size;
- PMM_PPOOL_FREE_BLOCK_HEADER FreeBlock =
- (PMM_PPOOL_FREE_BLOCK_HEADER)UsedBlock;
- PMM_PPOOL_FREE_BLOCK_HEADER NextBlock;
- PMM_PPOOL_FREE_BLOCK_HEADER NextNextBlock;
-
-#if MM_PPOOL_REDZONE_BYTES
- // write out buffer-overrun detection bytes
- {
- int i;
- PUCHAR Addr = (PUCHAR)Block;
- //DbgPrint ( "checking buffer-overrun detection bytes..." );
- for ( i = 0; i < MM_PPOOL_REDZONE_BYTES; i++ )
- {
- assert ( *(Addr-i-1) == MM_PPOOL_REDZONE_VALUE );
- assert ( *(Addr+UsedBlock->UserSize+i) == MM_PPOOL_REDZONE_VALUE );
- }
- //DbgPrint ( "done!\n" );
- }
-#endif//MM_PPOOL_REDZONE_BYTES
-
- ExAcquireFastMutex(&MmPagedPoolLock);
-
-#if MM_PPOOL_REDZONE_BYTES
- // remove from used list...
- {
- PMM_PPOOL_USED_BLOCK_HEADER pPrev = MmPagedPoolFirstUsedBlock;
- if ( pPrev == UsedBlock )
- {
- // special-case, our freeing block is first in list...
- MmPagedPoolFirstUsedBlock = pPrev->NextUsed;
- }
- else
- {
- while ( pPrev && pPrev->NextUsed != UsedBlock )
- pPrev = pPrev->NextUsed;
- // if this assert fails - memory has been corrupted
- // ( or I have a logic error...! )
- assert ( pPrev->NextUsed == UsedBlock );
- pPrev->NextUsed = UsedBlock->NextUsed;
- }
- }
-#endif//MM_PPOOL_REDZONE_BYTES
-
- /*
- * Begin setting up the newly freed block's header.
- */
- FreeBlock->Size = UsedSize;
- ASSERT_SIZE ( FreeBlock->Size );
-
- /*
- * Find the blocks immediately before and after the newly freed block on the free list.
- */
- PreviousBlock = NULL;
- NextBlock = MmPagedPoolFirstFreeBlock;
- while (NextBlock != NULL && NextBlock < FreeBlock)
- {
- PreviousBlock = NextBlock;
- NextBlock = NextBlock->NextFree;
- }
-
- /*
- * Insert the freed block on the free list.
- */
- if (PreviousBlock == NULL)
- {
- FreeBlock->NextFree = MmPagedPoolFirstFreeBlock;
- MmPagedPoolFirstFreeBlock = FreeBlock;
- }
- else
- {
- PreviousBlock->NextFree = FreeBlock;
- FreeBlock->NextFree = NextBlock;
- }
-
- /*
- * If the next block is immediately adjacent to the newly freed one then
- * merge them.
- */
- if (NextBlock != NULL &&
- ((char*)FreeBlock + FreeBlock->Size) == (char*)NextBlock)
- {
- FreeBlock->Size = FreeBlock->Size + NextBlock->Size;
- ASSERT_SIZE ( FreeBlock->Size );
- FreeBlock->NextFree = NextBlock->NextFree;
- NextNextBlock = NextBlock->NextFree;
- }
- else
- {
- NextNextBlock = NextBlock;
- }
-
- /*
- * If the previous block is adjacent to the newly freed one then
- * merge them.
- */
- if (PreviousBlock != NULL &&
- ((char*)PreviousBlock + PreviousBlock->Size) == (char*)FreeBlock)
- {
- PreviousBlock->Size = PreviousBlock->Size + FreeBlock->Size;
- ASSERT_SIZE ( PreviousBlock->Size );
- PreviousBlock->NextFree = NextNextBlock;
- }
-
- VerifyPagedPool();
-
- ExReleaseFastMutex(&MmPagedPoolLock);
+ printf ( "done!\n" );
+ return 0;
}
+#endif//PPOOL_UMODE_TEST
/* EOF */