Fix splitting of cells (noticed by Hartmut).
[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
47 INIT_FUNCTION
48 NTAPI
49 MmInitializePagedPool(VOID)
50 {
51 /*
52 * We are still at a high IRQL level at this point so explicitly commit
53 * the first page of the paged pool before writing the first block header.
54 */
55 MmCommitPagedPoolAddress ( (PVOID)MmPagedPoolBase, FALSE );
56
57 MmPagedPool = RPoolInit ( MmPagedPoolBase,
58 MmPagedPoolSize,
59 MM_POOL_ALIGNMENT,
60 MM_CACHE_LINE_SIZE,
61 PAGE_SIZE );
62
63 ExInitializeFastMutex(&MmPagedPool->Mutex);
64 }
65
66 /**********************************************************************
67 * NAME INTERNAL
68 * ExAllocatePagedPoolWithTag@12
69 *
70 * DESCRIPTION
71 *
72 * ARGUMENTS
73 *
74 * RETURN VALUE
75 */
76 PVOID STDCALL
77 ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
78 IN ULONG NumberOfBytes,
79 IN ULONG Tag)
80 {
81 int align;
82
83 if ( NumberOfBytes >= PAGE_SIZE )
84 align = 2;
85 else if ( PoolType & CACHE_ALIGNED_POOL_MASK )
86 align = 1;
87 else
88 align = 0;
89
90 ASSERT_IRQL(APC_LEVEL);
91
92 return RPoolAlloc ( MmPagedPool, NumberOfBytes, Tag, align );
93 }
94
95 VOID STDCALL
96 ExFreePagedPool(IN PVOID Block)
97 {
98 ASSERT_IRQL(APC_LEVEL);
99 RPoolFree ( MmPagedPool, Block );
100 }
101
102
103 #ifdef PPOOL_UMODE_TEST
104
105 PVOID TestAlloc ( ULONG Bytes )
106 {
107 PVOID ret;
108
109 //printf ( "Allocating block: " ); RPoolStats ( MmPagedPool );
110 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
111
112 ret = ExAllocatePagedPoolWithTag ( PagedPool, Bytes, 0 );
113
114 //printf ( "Block %x allocated: ", ret ); RPoolStats ( MmPagedPool );
115 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
116
117 return ret;
118 }
119
120 void TestFree ( PVOID ptr )
121 {
122 //printf ( "Freeing block %x: ", ptr ); RPoolStats ( MmPagedPool );
123 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
124 ExFreePagedPool(ptr);
125 //printf ( "Block %x freed: ", ptr ); RPoolStats ( MmPagedPool );
126 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
127 }
128
129 int main()
130 {
131 #define COUNT 100
132 int i, j;
133 char* keepers[COUNT];
134 char* trash[COUNT];
135 int AllocSize[] = { 15, 31, 63, 127, 255, 511, 1023, 2047 };
136 const int ALLOCS = sizeof(AllocSize) / sizeof(0[AllocSize]);
137 DWORD dwStart;
138
139 MmPagedPoolSize = 1*1024*1024;
140 MmPagedPoolBase = malloc ( MmPagedPoolSize );
141 MmInitializePagedPool();
142
143 dwStart = GetTickCount();
144
145 printf ( "test #1 phase #1\n" );
146 for ( i = 0; i < COUNT; i++ )
147 {
148 //printf ( "keeper %i) ", i );
149 keepers[i] = TestAlloc ( AllocSize[i%ALLOCS] );
150 if ( !keepers[i] ) printf ( "allocation failed\n" );
151 //printf ( "trash %i) ", i );
152 trash[i] = TestAlloc ( AllocSize[i%ALLOCS] );
153 if ( !trash[i] ) printf ( "allocation failed\n" );
154 }
155
156 printf ( "test #1 phase #2\n" );
157 for ( i = 0; i < COUNT; i++ )
158 {
159 if ( i == 6 )
160 i = i;
161 //printf ( "%i) ", i );
162 TestFree ( trash[i] );
163 }
164
165 printf ( "test #1 phase #3\n" );
166 for ( i = 0; i < 4; i++ )
167 {
168 //printf ( "%i) ", i );
169 keepers[i] = TestAlloc ( 4096 );
170 if ( !keepers[i] ) printf ( "allocation failed\n" );
171 }
172
173 printf ( "test #1 phase #4\n" );
174 for ( i = 0; i < 4; i++ )
175 {
176 //printf ( "%i) ", i );
177 TestFree ( keepers[i] );
178 }
179
180 printf ( "test #1 phase #5\n" );
181 srand(1);
182 for ( i = 0; i < COUNT; i++ )
183 {
184 //printf ( "%i) ", i );
185 trash[i] = TestAlloc ( rand()%1024+1 );
186 if ( !trash[i] ) printf ( "allocation failed\n" );
187 }
188 printf ( "test #1 phase #6\n" );
189 for ( i = 0; i < 10000; i++ )
190 {
191 TestFree ( trash[i%COUNT] );
192 trash[i%COUNT] = TestAlloc ( rand()%1024+1 );
193 if ( !trash[i%COUNT] ) printf ( "allocation failed\n" );
194 }
195 printf ( "test #1 phase #7\n" );
196 j = 0;
197 for ( i = 0; i < COUNT; i++ )
198 {
199 if ( trash[i] )
200 {
201 TestFree ( trash[i] );
202 ++j;
203 }
204 }
205 printf ( "test #1 phase #8 ( freed %i of %i trash )\n", j, COUNT );
206 if ( !TestAlloc ( 2048 ) )
207 printf ( "Couldn't allocate 2048 bytes after freeing up a whole bunch of blocks\n" );
208
209 free ( MmPagedPoolBase );
210
211 printf ( "test time: %lu\n", GetTickCount() - dwStart );
212
213 printf ( "test #2\n" );
214
215 MmPagedPoolSize = 1024;
216 MmPagedPoolBase = malloc ( MmPagedPoolSize );
217 MmInitializePagedPool();
218
219 TestAlloc ( 512 );
220 i = RPoolLargestAllocPossible ( MmPagedPool, 0 );
221 if ( !TestAlloc ( i ) )
222 {
223 printf ( "allocating last available block failed\n" );
224 }
225
226 free ( MmPagedPoolBase );
227
228 printf ( "done!\n" );
229 return 0;
230 }
231 #endif//PPOOL_UMODE_TEST
232
233 /* EOF */