completely rewritten PagedPool.
[reactos.git] / reactos / ntoskrnl / mm / ppool.c
1 /* $Id: ppool.c,v 1.37 2004/12/17 13:20:05 royce Exp $
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/ppool.c
6 * PURPOSE: Implements the paged pool
7 * PROGRAMMER: David Welch (welch@mcmail.com)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 * Complete Rewrite Dec 2004 by Royce Mitchell III
11 */
12
13 /* INCLUDES *****************************************************************/
14
15 #ifdef PPOOL_UMODE_TEST
16 #include "ppool_umode.h"
17 #else//PPOOL_UMODE_TEST
18 #include <ntoskrnl.h>
19 #define NDEBUG
20 #include <internal/debug.h>
21 #endif//PPOOL_UMODE_TEST
22
23 #undef ASSERT
24 #define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
25
26 // enable "magic"
27 //#define R_MAGIC
28 #define R_MUTEX FAST_MUTEX
29 #define R_ACQUIRE_MUTEX(pool) /*DPRINT1("Acquiring PPool Mutex\n");*/ ExAcquireFastMutex(&pool->Mutex)
30 #define R_RELEASE_MUTEX(pool) /*DPRINT1("Releasing PPool Mutex\n");*/ ExReleaseFastMutex(&pool->Mutex)
31 #define R_PRINT_ADDRESS(addr) 0
32 #define R_PANIC() KeBugCheck(0)
33 #define R_DEBUG DbgPrint
34 #define R_EXTRA_STACK_UP 2
35
36 #include "RPoolMgr.h"
37
38 /* GLOBALS *******************************************************************/
39
40 PVOID MmPagedPoolBase;
41 ULONG MmPagedPoolSize;
42 ULONG MmTotalPagedPoolQuota = 0; // TODO FIXME commented out until we use it
43 static PR_POOL MmPagedPool = NULL;
44
45 /* FUNCTIONS *****************************************************************/
46
47 VOID INIT_FUNCTION
48 MmInitializePagedPool()
49 {
50 /*
51 * We are still at a high IRQL level at this point so explicitly commit
52 * the first page of the paged pool before writing the first block header.
53 */
54 MmCommitPagedPoolAddress ( (PVOID)MmPagedPoolBase, FALSE );
55
56 MmPagedPool = RPoolInit ( MmPagedPoolBase,
57 MmPagedPoolSize,
58 MM_POOL_ALIGNMENT,
59 MM_CACHE_LINE_SIZE,
60 PAGE_SIZE );
61
62 ExInitializeFastMutex(&MmPagedPool->Mutex);
63 }
64
65 /**********************************************************************
66 * NAME INTERNAL
67 * ExAllocatePagedPoolWithTag@12
68 *
69 * DESCRIPTION
70 *
71 * ARGUMENTS
72 *
73 * RETURN VALUE
74 */
75 PVOID STDCALL
76 ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
77 IN ULONG NumberOfBytes,
78 IN ULONG Tag)
79 {
80 int align;
81
82 if ( NumberOfBytes >= PAGE_SIZE )
83 align = 2;
84 else if ( PoolType == PagedPoolCacheAligned )
85 align = 1;
86 else
87 align = 0;
88
89 ASSERT_IRQL(APC_LEVEL);
90
91 return RPoolAlloc ( MmPagedPool, NumberOfBytes, Tag, align );
92 }
93
94 VOID STDCALL
95 ExFreePagedPool(IN PVOID Block)
96 {
97 ASSERT_IRQL(APC_LEVEL);
98 RPoolFree ( MmPagedPool, Block );
99 }
100
101 VOID STDCALL
102 ExRosDumpPagedPoolByTag ( ULONG Tag )
103 {
104 // TODO FIXME - should we ASSERT_IRQL?
105 RPoolDumpByTag ( MmPagedPool, Tag );
106 }
107
108 ULONG STDCALL
109 ExRosQueryPagedPoolTag ( PVOID Addr )
110 {
111 // TODO FIXME - should we ASSERT_IRQL?
112 return RPoolQueryTag ( Addr );
113 }
114
115 #ifdef PPOOL_UMODE_TEST
116
117 PVOID TestAlloc ( ULONG Bytes )
118 {
119 PVOID ret;
120
121 //printf ( "Allocating block: " ); RPoolStats ( MmPagedPool );
122 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
123
124 ret = ExAllocatePagedPoolWithTag ( PagedPool, Bytes, 0 );
125
126 //printf ( "Block %x allocated: ", ret ); RPoolStats ( MmPagedPool );
127 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
128
129 return ret;
130 }
131
132 void TestFree ( PVOID ptr )
133 {
134 //printf ( "Freeing block %x: ", ptr ); RPoolStats ( MmPagedPool );
135 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
136 ExFreePagedPool(ptr);
137 //printf ( "Block %x freed: ", ptr ); RPoolStats ( MmPagedPool );
138 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
139 }
140
141 int main()
142 {
143 #define COUNT 100
144 int i, j;
145 char* keepers[COUNT];
146 char* trash[COUNT];
147 int AllocSize[] = { 15, 31, 63, 127, 255, 511, 1023, 2047 };
148 const int ALLOCS = sizeof(AllocSize) / sizeof(0[AllocSize]);
149 DWORD dwStart;
150
151 MmPagedPoolSize = 1*1024*1024;
152 MmPagedPoolBase = malloc ( MmPagedPoolSize );
153 MmInitializePagedPool();
154
155 dwStart = GetTickCount();
156
157 printf ( "test #1 phase #1\n" );
158 for ( i = 0; i < COUNT; i++ )
159 {
160 //printf ( "keeper %i) ", i );
161 keepers[i] = TestAlloc ( AllocSize[i%ALLOCS] );
162 if ( !keepers[i] ) printf ( "allocation failed\n" );
163 //printf ( "trash %i) ", i );
164 trash[i] = TestAlloc ( AllocSize[i%ALLOCS] );
165 if ( !trash[i] ) printf ( "allocation failed\n" );
166 }
167
168 printf ( "test #1 phase #2\n" );
169 for ( i = 0; i < COUNT; i++ )
170 {
171 if ( i == 6 )
172 i = i;
173 //printf ( "%i) ", i );
174 TestFree ( trash[i] );
175 }
176
177 printf ( "test #1 phase #3\n" );
178 for ( i = 0; i < 4; i++ )
179 {
180 //printf ( "%i) ", i );
181 keepers[i] = TestAlloc ( 4096 );
182 if ( !keepers[i] ) printf ( "allocation failed\n" );
183 }
184
185 printf ( "test #1 phase #4\n" );
186 for ( i = 0; i < 4; i++ )
187 {
188 //printf ( "%i) ", i );
189 TestFree ( keepers[i] );
190 }
191
192 printf ( "test #1 phase #5\n" );
193 srand(1);
194 for ( i = 0; i < COUNT; i++ )
195 {
196 //printf ( "%i) ", i );
197 trash[i] = TestAlloc ( rand()%1024+1 );
198 if ( !trash[i] ) printf ( "allocation failed\n" );
199 }
200 printf ( "test #1 phase #6\n" );
201 for ( i = 0; i < 10000; i++ )
202 {
203 TestFree ( trash[i%COUNT] );
204 trash[i%COUNT] = TestAlloc ( rand()%1024+1 );
205 if ( !trash[i%COUNT] ) printf ( "allocation failed\n" );
206 }
207 printf ( "test #1 phase #7\n" );
208 j = 0;
209 for ( i = 0; i < COUNT; i++ )
210 {
211 if ( trash[i] )
212 {
213 TestFree ( trash[i] );
214 ++j;
215 }
216 }
217 printf ( "test #1 phase #8 ( freed %i of %i trash )\n", j, COUNT );
218 if ( !TestAlloc ( 2048 ) )
219 printf ( "Couldn't allocate 2048 bytes after freeing up a whole bunch of blocks\n" );
220
221 free ( MmPagedPoolBase );
222
223 printf ( "test time: %lu\n", GetTickCount() - dwStart );
224
225 printf ( "test #2\n" );
226
227 MmPagedPoolSize = 1024;
228 MmPagedPoolBase = malloc ( MmPagedPoolSize );
229 MmInitializePagedPool();
230
231 TestAlloc ( 512 );
232 i = RPoolLargestAllocPossible ( MmPagedPool, 0 );
233 if ( !TestAlloc ( i ) )
234 {
235 printf ( "allocating last available block failed\n" );
236 }
237
238 free ( MmPagedPoolBase );
239
240 printf ( "done!\n" );
241 return 0;
242 }
243 #endif//PPOOL_UMODE_TEST
244
245 /* EOF */