Release the rmap list lock after cleaning the head entry in MmDeleteAllRmaps. This...
[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 #if defined (ALLOC_PRAGMA)
23 #pragma alloc_text(INIT, MmInitializePagedPool)
24 #endif
25
26 #undef ASSERT
27 #define ASSERT(x) if (!(x)) {DbgPrint("Assertion "#x" failed at %s:%d\n", __FILE__,__LINE__); KeBugCheck(0); }
28
29 // enable "magic"
30 //#define R_MAGIC
31 #define R_MUTEX FAST_MUTEX
32 #define R_ACQUIRE_MUTEX(pool) /*DPRINT1("Acquiring PPool Mutex\n");*/ ExAcquireFastMutex(&pool->Mutex)
33 #define R_RELEASE_MUTEX(pool) /*DPRINT1("Releasing PPool Mutex\n");*/ ExReleaseFastMutex(&pool->Mutex)
34 #define R_PRINT_ADDRESS(addr) KeRosPrintAddress(addr)
35 #define R_PANIC() KeBugCheck(0)
36 #define R_DEBUG DbgPrint
37 #define R_GET_STACK_FRAMES(ptr,cnt) KeRosGetStackFrames(ptr,cnt)
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 STDCALL
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(APC_LEVEL);
95
96 return RPoolAlloc ( MmPagedPool, NumberOfBytes, Tag, align );
97 }
98
99 VOID STDCALL
100 ExFreePagedPool(IN PVOID Block)
101 {
102 ASSERT_IRQL(APC_LEVEL);
103 RPoolFree ( MmPagedPool, Block );
104 }
105
106
107 #ifdef PPOOL_UMODE_TEST
108
109 PVOID TestAlloc ( ULONG Bytes )
110 {
111 PVOID ret;
112
113 //printf ( "Allocating block: " ); RPoolStats ( MmPagedPool );
114 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
115
116 ret = ExAllocatePagedPoolWithTag ( PagedPool, Bytes, 0 );
117
118 //printf ( "Block %x allocated: ", ret ); RPoolStats ( MmPagedPool );
119 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
120
121 return ret;
122 }
123
124 void TestFree ( PVOID ptr )
125 {
126 //printf ( "Freeing block %x: ", ptr ); RPoolStats ( MmPagedPool );
127 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
128 ExFreePagedPool(ptr);
129 //printf ( "Block %x freed: ", ptr ); RPoolStats ( MmPagedPool );
130 //RPoolRedZoneCheck ( MmPagedPool, __FILE__, __LINE__ );
131 }
132
133 int main()
134 {
135 #define COUNT 100
136 int i, j;
137 char* keepers[COUNT];
138 char* trash[COUNT];
139 int AllocSize[] = { 15, 31, 63, 127, 255, 511, 1023, 2047 };
140 const int ALLOCS = sizeof(AllocSize) / sizeof(0[AllocSize]);
141 DWORD dwStart;
142
143 MmPagedPoolSize = 1*1024*1024;
144 MmPagedPoolBase = malloc ( MmPagedPoolSize );
145 MmInitializePagedPool();
146
147 dwStart = GetTickCount();
148
149 printf ( "test #1 phase #1\n" );
150 for ( i = 0; i < COUNT; i++ )
151 {
152 //printf ( "keeper %i) ", i );
153 keepers[i] = TestAlloc ( AllocSize[i%ALLOCS] );
154 if ( !keepers[i] ) printf ( "allocation failed\n" );
155 //printf ( "trash %i) ", i );
156 trash[i] = TestAlloc ( AllocSize[i%ALLOCS] );
157 if ( !trash[i] ) printf ( "allocation failed\n" );
158 }
159
160 printf ( "test #1 phase #2\n" );
161 for ( i = 0; i < COUNT; i++ )
162 {
163 if ( i == 6 )
164 i = i;
165 //printf ( "%i) ", i );
166 TestFree ( trash[i] );
167 }
168
169 printf ( "test #1 phase #3\n" );
170 for ( i = 0; i < 4; i++ )
171 {
172 //printf ( "%i) ", i );
173 keepers[i] = TestAlloc ( 4096 );
174 if ( !keepers[i] ) printf ( "allocation failed\n" );
175 }
176
177 printf ( "test #1 phase #4\n" );
178 for ( i = 0; i < 4; i++ )
179 {
180 //printf ( "%i) ", i );
181 TestFree ( keepers[i] );
182 }
183
184 printf ( "test #1 phase #5\n" );
185 srand(1);
186 for ( i = 0; i < COUNT; i++ )
187 {
188 //printf ( "%i) ", i );
189 trash[i] = TestAlloc ( rand()%1024+1 );
190 if ( !trash[i] ) printf ( "allocation failed\n" );
191 }
192 printf ( "test #1 phase #6\n" );
193 for ( i = 0; i < 10000; i++ )
194 {
195 TestFree ( trash[i%COUNT] );
196 trash[i%COUNT] = TestAlloc ( rand()%1024+1 );
197 if ( !trash[i%COUNT] ) printf ( "allocation failed\n" );
198 }
199 printf ( "test #1 phase #7\n" );
200 j = 0;
201 for ( i = 0; i < COUNT; i++ )
202 {
203 if ( trash[i] )
204 {
205 TestFree ( trash[i] );
206 ++j;
207 }
208 }
209 printf ( "test #1 phase #8 ( freed %i of %i trash )\n", j, COUNT );
210 if ( !TestAlloc ( 2048 ) )
211 printf ( "Couldn't allocate 2048 bytes after freeing up a whole bunch of blocks\n" );
212
213 free ( MmPagedPoolBase );
214
215 printf ( "test time: %lu\n", GetTickCount() - dwStart );
216
217 printf ( "test #2\n" );
218
219 MmPagedPoolSize = 1024;
220 MmPagedPoolBase = malloc ( MmPagedPoolSize );
221 MmInitializePagedPool();
222
223 TestAlloc ( 512 );
224 i = RPoolLargestAllocPossible ( MmPagedPool, 0 );
225 if ( !TestAlloc ( i ) )
226 {
227 printf ( "allocating last available block failed\n" );
228 }
229
230 free ( MmPagedPoolBase );
231
232 printf ( "done!\n" );
233 return 0;
234 }
235 #endif//PPOOL_UMODE_TEST
236
237 /* EOF */