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