2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/ppool.c
5 * PURPOSE: Implements the paged pool
7 * PROGRAMMERS: David Welch (welch@mcmail.com)
11 /* INCLUDES *****************************************************************/
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, MmInitializePagedPool)
22 #define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
26 #define R_MUTEX FAST_MUTEX
27 #define R_ACQUIRE_MUTEX(pool) /*DPRINT1("Acquiring PPool Mutex\n");*/ ExAcquireFastMutex(&pool->Mutex)
28 #define R_RELEASE_MUTEX(pool) /*DPRINT1("Releasing PPool Mutex\n");*/ ExReleaseFastMutex(&pool->Mutex)
29 #define R_PRINT_ADDRESS(addr) KeRosPrintAddress(addr)
30 #define R_PANIC() KeBugCheck(0)
31 #define R_DEBUG DbgPrint
34 #define R_GET_STACK_FRAMES(ptr,cnt)
36 #define R_GET_STACK_FRAMES(ptr,cnt) RtlWalkFrameChain((PVOID*)ptr,cnt, 0)
41 /* GLOBALS *******************************************************************/
43 PVOID MmPagedPoolBase
;
44 ULONG MmPagedPoolSize
;
45 ULONG MmTotalPagedPoolQuota
= 0; // TODO FIXME commented out until we use it
46 static PR_POOL MmPagedPool
= NULL
;
48 /* FUNCTIONS *****************************************************************/
53 MmInitializePagedPool(VOID
)
56 PHYSICAL_ADDRESS BoundaryAddressMultiple
;
58 BoundaryAddressMultiple
.QuadPart
= 0;
60 BaseAddress
= MmPagedPoolBase
;
61 MmCreateMemoryArea(MmGetKernelAddressSpace(),
62 MEMORY_AREA_PAGED_POOL
,
69 BoundaryAddressMultiple
);
72 * We are still at a high IRQL level at this point so explicitly commit
73 * the first page of the paged pool before writing the first block header.
75 MmCommitPagedPoolAddress ( (PVOID
)MmPagedPoolBase
, FALSE
);
77 MmPagedPool
= RPoolInit ( MmPagedPoolBase
,
83 ExInitializeFastMutex(&MmPagedPool
->Mutex
);
86 /**********************************************************************
88 * ExAllocatePagedPoolWithTag@12
97 ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType
,
98 IN ULONG NumberOfBytes
,
103 if ( NumberOfBytes
>= PAGE_SIZE
)
105 else if ( PoolType
& CACHE_ALIGNED_POOL_MASK
)
110 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL
);
112 return RPoolAlloc ( MmPagedPool
, NumberOfBytes
, Tag
, align
);
116 ExFreePagedPool(IN PVOID Block
)
118 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL
);
119 RPoolFree ( MmPagedPool
, Block
);
123 EiGetPagedPoolTag(IN PVOID Block
)
125 return RBodyToHdr(Block
)->Tag
;
129 #ifdef PPOOL_UMODE_TEST
131 PVOID
TestAlloc ( ULONG Bytes
)
135 //printf ( "Allocating block: " ); RPoolStats ( MmPagedPool );
136 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
138 ret
= ExAllocatePagedPoolWithTag ( PagedPool
, Bytes
, 0 );
140 //printf ( "Block %x allocated: ", ret ); RPoolStats ( MmPagedPool );
141 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
146 void TestFree ( PVOID ptr
)
148 //printf ( "Freeing block %x: ", ptr ); RPoolStats ( MmPagedPool );
149 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
150 ExFreePagedPool(ptr
);
151 //printf ( "Block %x freed: ", ptr ); RPoolStats ( MmPagedPool );
152 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
159 char* keepers
[COUNT
];
161 int AllocSize
[] = { 15, 31, 63, 127, 255, 511, 1023, 2047 };
162 const int ALLOCS
= sizeof(AllocSize
) / sizeof(0[AllocSize
]);
165 MmPagedPoolSize
= 1*1024*1024;
166 MmPagedPoolBase
= malloc ( MmPagedPoolSize
);
167 MmInitializePagedPool();
169 dwStart
= GetTickCount();
171 printf ( "test #1 phase #1\n" );
172 for ( i
= 0; i
< COUNT
; i
++ )
174 //printf ( "keeper %i) ", i );
175 keepers
[i
] = TestAlloc ( AllocSize
[i
%ALLOCS
] );
176 if ( !keepers
[i
] ) printf ( "allocation failed\n" );
177 //printf ( "trash %i) ", i );
178 trash
[i
] = TestAlloc ( AllocSize
[i
%ALLOCS
] );
179 if ( !trash
[i
] ) printf ( "allocation failed\n" );
182 printf ( "test #1 phase #2\n" );
183 for ( i
= 0; i
< COUNT
; i
++ )
187 //printf ( "%i) ", i );
188 TestFree ( trash
[i
] );
191 printf ( "test #1 phase #3\n" );
192 for ( i
= 0; i
< 4; i
++ )
194 //printf ( "%i) ", i );
195 keepers
[i
] = TestAlloc ( 4096 );
196 if ( !keepers
[i
] ) printf ( "allocation failed\n" );
199 printf ( "test #1 phase #4\n" );
200 for ( i
= 0; i
< 4; i
++ )
202 //printf ( "%i) ", i );
203 TestFree ( keepers
[i
] );
206 printf ( "test #1 phase #5\n" );
208 for ( i
= 0; i
< COUNT
; i
++ )
210 //printf ( "%i) ", i );
211 trash
[i
] = TestAlloc ( rand()%1024+1 );
212 if ( !trash
[i
] ) printf ( "allocation failed\n" );
214 printf ( "test #1 phase #6\n" );
215 for ( i
= 0; i
< 10000; i
++ )
217 TestFree ( trash
[i
%COUNT
] );
218 trash
[i
%COUNT
] = TestAlloc ( rand()%1024+1 );
219 if ( !trash
[i
%COUNT
] ) printf ( "allocation failed\n" );
221 printf ( "test #1 phase #7\n" );
223 for ( i
= 0; i
< COUNT
; i
++ )
227 TestFree ( trash
[i
] );
231 printf ( "test #1 phase #8 ( freed %i of %i trash )\n", j
, COUNT
);
232 if ( !TestAlloc ( 2048 ) )
233 printf ( "Couldn't allocate 2048 bytes after freeing up a whole bunch of blocks\n" );
235 free ( MmPagedPoolBase
);
237 printf ( "test time: %lu\n", GetTickCount() - dwStart
);
239 printf ( "test #2\n" );
241 MmPagedPoolSize
= 1024;
242 MmPagedPoolBase
= malloc ( MmPagedPoolSize
);
243 MmInitializePagedPool();
246 i
= RPoolLargestAllocPossible ( MmPagedPool
, 0 );
247 if ( !TestAlloc ( i
) )
249 printf ( "allocating last available block failed\n" );
252 free ( MmPagedPoolBase
);
254 printf ( "done!\n" );
257 #endif//PPOOL_UMODE_TEST