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