Merge HAL changes 34743, 34812, 34839, 34917, 35515, 35771, 35902, 35904,
[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 PVOID BaseAddress;
56 PHYSICAL_ADDRESS BoundaryAddressMultiple;
57 PMEMORY_AREA MArea;
58 BoundaryAddressMultiple.QuadPart = 0;
59
60 BaseAddress = MmPagedPoolBase;
61 MmCreateMemoryArea(MmGetKernelAddressSpace(),
62 MEMORY_AREA_PAGED_POOL,
63 &BaseAddress,
64 MmPagedPoolSize,
65 PAGE_READWRITE,
66 &MArea,
67 TRUE,
68 0,
69 BoundaryAddressMultiple);
70
71 /*
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.
74 */
75 MmCommitPagedPoolAddress ( (PVOID)MmPagedPoolBase, FALSE );
76
77 MmPagedPool = RPoolInit ( MmPagedPoolBase,
78 MmPagedPoolSize,
79 MM_POOL_ALIGNMENT,
80 MM_CACHE_LINE_SIZE,
81 PAGE_SIZE );
82
83 ExInitializeFastMutex(&MmPagedPool->Mutex);
84 }
85
86 /**********************************************************************
87 * NAME INTERNAL
88 * ExAllocatePagedPoolWithTag@12
89 *
90 * DESCRIPTION
91 *
92 * ARGUMENTS
93 *
94 * RETURN VALUE
95 */
96 PVOID NTAPI
97 ExAllocatePagedPoolWithTag (IN POOL_TYPE PoolType,
98 IN ULONG NumberOfBytes,
99 IN ULONG Tag)
100 {
101 int align;
102
103 if ( NumberOfBytes >= PAGE_SIZE )
104 align = 2;
105 else if ( PoolType & CACHE_ALIGNED_POOL_MASK )
106 align = 1;
107 else
108 align = 0;
109
110 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
111
112 return RPoolAlloc ( MmPagedPool, NumberOfBytes, Tag, align );
113 }
114
115 VOID NTAPI
116 ExFreePagedPool(IN PVOID Block)
117 {
118 ASSERT_IRQL_LESS_OR_EQUAL(APC_LEVEL);
119 RPoolFree ( MmPagedPool, Block );
120 }
121
122 ULONG NTAPI
123 EiGetPagedPoolTag(IN PVOID Block)
124 {
125 return RBodyToHdr(Block)->Tag;
126 }
127
128
129 #ifdef PPOOL_UMODE_TEST
130
131 PVOID TestAlloc ( ULONG Bytes )
132 {
133 PVOID ret;
134
135 //printf ( "Allocating block: " ); RPoolStats ( MmPagedPool );
136 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
137
138 ret = ExAllocatePagedPoolWithTag ( PagedPool, Bytes, 0 );
139
140 //printf ( "Block %x allocated: ", ret ); RPoolStats ( MmPagedPool );
141 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
142
143 return ret;
144 }
145
146 void TestFree ( PVOID ptr )
147 {
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__ );
153 }
154
155 int main()
156 {
157 #define COUNT 100
158 int i, j;
159 char* keepers[COUNT];
160 char* trash[COUNT];
161 int AllocSize[] = { 15, 31, 63, 127, 255, 511, 1023, 2047 };
162 const int ALLOCS = sizeof(AllocSize) / sizeof(0[AllocSize]);
163 ULONG dwStart;
164
165 MmPagedPoolSize = 1*1024*1024;
166 MmPagedPoolBase = malloc ( MmPagedPoolSize );
167 MmInitializePagedPool();
168
169 dwStart = GetTickCount();
170
171 printf ( "test #1 phase #1\n" );
172 for ( i = 0; i < COUNT; i++ )
173 {
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" );
180 }
181
182 printf ( "test #1 phase #2\n" );
183 for ( i = 0; i < COUNT; i++ )
184 {
185 if ( i == 6 )
186 i = i;
187 //printf ( "%i) ", i );
188 TestFree ( trash[i] );
189 }
190
191 printf ( "test #1 phase #3\n" );
192 for ( i = 0; i < 4; i++ )
193 {
194 //printf ( "%i) ", i );
195 keepers[i] = TestAlloc ( 4096 );
196 if ( !keepers[i] ) printf ( "allocation failed\n" );
197 }
198
199 printf ( "test #1 phase #4\n" );
200 for ( i = 0; i < 4; i++ )
201 {
202 //printf ( "%i) ", i );
203 TestFree ( keepers[i] );
204 }
205
206 printf ( "test #1 phase #5\n" );
207 srand(1);
208 for ( i = 0; i < COUNT; i++ )
209 {
210 //printf ( "%i) ", i );
211 trash[i] = TestAlloc ( rand()%1024+1 );
212 if ( !trash[i] ) printf ( "allocation failed\n" );
213 }
214 printf ( "test #1 phase #6\n" );
215 for ( i = 0; i < 10000; i++ )
216 {
217 TestFree ( trash[i%COUNT] );
218 trash[i%COUNT] = TestAlloc ( rand()%1024+1 );
219 if ( !trash[i%COUNT] ) printf ( "allocation failed\n" );
220 }
221 printf ( "test #1 phase #7\n" );
222 j = 0;
223 for ( i = 0; i < COUNT; i++ )
224 {
225 if ( trash[i] )
226 {
227 TestFree ( trash[i] );
228 ++j;
229 }
230 }
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" );
234
235 free ( MmPagedPoolBase );
236
237 printf ( "test time: %lu\n", GetTickCount() - dwStart );
238
239 printf ( "test #2\n" );
240
241 MmPagedPoolSize = 1024;
242 MmPagedPoolBase = malloc ( MmPagedPoolSize );
243 MmInitializePagedPool();
244
245 TestAlloc ( 512 );
246 i = RPoolLargestAllocPossible ( MmPagedPool, 0 );
247 if ( !TestAlloc ( i ) )
248 {
249 printf ( "allocating last available block failed\n" );
250 }
251
252 free ( MmPagedPoolBase );
253
254 printf ( "done!\n" );
255 return 0;
256 }
257 #endif//PPOOL_UMODE_TEST
258
259 /* EOF */