- Make the NDK compatible with the MSDDK again.
[reactos.git] / reactos / ntoskrnl / mm / pool.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/pool.c
6 * PURPOSE: Implements the kernel memory pool
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES ****************************************************************/
12
13 #include <ntoskrnl.h>
14
15 #define NDEBUG
16 #include <internal/debug.h>
17
18 extern ULONG MiNonPagedPoolLength;
19 extern ULONG MmTotalPagedPoolQuota;
20 extern ULONG MmTotalNonPagedPoolQuota;
21 extern MM_STATS MmStats;
22
23 /* FUNCTIONS ***************************************************************/
24
25 STATIC PVOID STDCALL
26 EiAllocatePool(POOL_TYPE PoolType,
27 ULONG NumberOfBytes,
28 ULONG Tag,
29 PVOID Caller)
30 {
31 PVOID Block;
32
33 /* FIXME: Handle SESSION_POOL_MASK, VERIFIER_POOL_MASK, QUOTA_POOL_MASK */
34 if (PoolType & PAGED_POOL_MASK)
35 {
36 Block = ExAllocatePagedPoolWithTag(PoolType,NumberOfBytes,Tag);
37 }
38 else
39 {
40 Block = ExAllocateNonPagedPoolWithTag(PoolType,NumberOfBytes,Tag,Caller);
41 }
42
43 if ((PoolType & MUST_SUCCEED_POOL_MASK) && Block==NULL)
44 {
45 KEBUGCHECK(MUST_SUCCEED_POOL_EMPTY);
46 }
47 return(Block);
48 }
49
50 /*
51 * @implemented
52 */
53 PVOID STDCALL
54 ExAllocatePool (POOL_TYPE PoolType, ULONG NumberOfBytes)
55 /*
56 * FUNCTION: Allocates pool memory of a specified type and returns a pointer
57 * to the allocated block. This routine is used for general purpose allocation
58 * of memory
59 * ARGUMENTS:
60 * PoolType
61 * Specifies the type of memory to allocate which can be one
62 * of the following:
63 *
64 * NonPagedPool
65 * NonPagedPoolMustSucceed
66 * NonPagedPoolCacheAligned
67 * NonPagedPoolCacheAlignedMustS
68 * PagedPool
69 * PagedPoolCacheAligned
70 *
71 * NumberOfBytes
72 * Specifies the number of bytes to allocate
73 * RETURNS: The allocated block on success
74 * NULL on failure
75 */
76 {
77 PVOID Block;
78
79 #if defined(__GNUC__)
80
81 Block = EiAllocatePool(PoolType,
82 NumberOfBytes,
83 TAG_NONE,
84 (PVOID)__builtin_return_address(0));
85 #elif defined(_MSC_VER)
86
87 Block = EiAllocatePool(PoolType,
88 NumberOfBytes,
89 TAG_NONE,
90 &ExAllocatePool);
91 #else
92 #error Unknown compiler
93 #endif
94
95 return(Block);
96 }
97
98
99 /*
100 * @implemented
101 */
102 PVOID STDCALL
103 ExAllocatePoolWithTag (POOL_TYPE PoolType, ULONG NumberOfBytes, ULONG Tag)
104 {
105 PVOID Block;
106
107 #if defined(__GNUC__)
108
109 Block = EiAllocatePool(PoolType,
110 NumberOfBytes,
111 Tag,
112 (PVOID)__builtin_return_address(0));
113 #elif defined(_MSC_VER)
114
115 Block = EiAllocatePool(PoolType,
116 NumberOfBytes,
117 Tag,
118 &ExAllocatePoolWithTag);
119 #else
120 #error Unknown compiler
121 #endif
122
123 return(Block);
124 }
125
126
127 /*
128 * @implemented
129 */
130 PVOID STDCALL
131 ExAllocatePoolWithQuota (POOL_TYPE PoolType, ULONG NumberOfBytes)
132 {
133 return(ExAllocatePoolWithQuotaTag(PoolType, NumberOfBytes, TAG_NONE));
134 }
135
136 /*
137 * @implemented
138 */
139 PVOID
140 STDCALL
141 ExAllocatePoolWithTagPriority(
142 IN POOL_TYPE PoolType,
143 IN SIZE_T NumberOfBytes,
144 IN ULONG Tag,
145 IN EX_POOL_PRIORITY Priority
146 )
147 {
148 /* Check if this is one of the "Special" Flags, used by the Verifier */
149 if (Priority & 8) {
150 /* Check if this is a xxSpecialUnderrun */
151 if (Priority & 1) {
152 return MiAllocateSpecialPool(PoolType, NumberOfBytes, Tag, 1);
153 } else { /* xxSpecialOverrun */
154 return MiAllocateSpecialPool(PoolType, NumberOfBytes, Tag, 0);
155 }
156 }
157
158 /* FIXME: Do Ressource Checking Based on Priority and fail if resources too low*/
159
160 /* Do the allocation */
161 return ExAllocatePoolWithTag(PoolType, NumberOfBytes, Tag);
162 }
163
164 /*
165 * @implemented
166 */
167 PVOID STDCALL
168 ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType,
169 IN ULONG NumberOfBytes,
170 IN ULONG Tag)
171 {
172 PVOID Block;
173 PEPROCESS Process;
174
175 /* Allocate the Pool First */
176 Block = EiAllocatePool(PoolType,
177 NumberOfBytes,
178 Tag,
179 &ExAllocatePoolWithQuotaTag);
180
181 /* "Quota is not charged to the thread for allocations >= PAGE_SIZE" - OSR Docs */
182 if (!(NumberOfBytes >= PAGE_SIZE)) {
183
184 /* Get the Current Process */
185 Process = PsGetCurrentProcess();
186
187 /* PsChargePoolQuota returns an exception, so this needs SEH */
188 #if defined(__GNUC__)
189 _SEH_FILTER(FreeAndGoOn) {
190 /* Couldn't charge, so free the pool and let the caller SEH manage */
191 ExFreePool(Block);
192 return EXCEPTION_CONTINUE_SEARCH;
193 } _SEH_TRY {
194 //* FIXME: Is there a way to get the actual Pool size allocated from the pool header? */
195 PsChargePoolQuota(Process, PoolType & PAGED_POOL_MASK, NumberOfBytes);
196 } _SEH_EXCEPT(FreeAndGoOn) {
197 /* Quota Exceeded and the caller had no SEH! */
198 KeBugCheck(STATUS_QUOTA_EXCEEDED);
199 } _SEH_END;
200 #else /* assuming all other Win32 compilers understand SEH */
201 __try {
202 PsChargePoolQuota(Process, PoolType & PAGED_POOL_MASK, NumberOfBytes);
203 }
204 __except (ExFreePool(Block), EXCEPTION_CONTINUE_SEARCH) {
205 KeBugCheck(STATUS_QUOTA_EXCEEDED);
206 }
207 #endif
208 }
209
210 return Block;
211 }
212
213 /*
214 * @implemented
215 */
216 VOID STDCALL
217 ExFreePool(IN PVOID Block)
218 {
219 ASSERT_IRQL(DISPATCH_LEVEL);
220
221 if (Block >= MmPagedPoolBase && (char*)Block < ((char*)MmPagedPoolBase + MmPagedPoolSize))
222 {
223 ExFreePagedPool(Block);
224 }
225 else
226 {
227 ExFreeNonPagedPool(Block);
228 }
229 }
230
231 /*
232 * @implemented
233 */
234 VOID STDCALL
235 ExFreePoolWithTag(IN PVOID Block, IN ULONG Tag)
236 {
237 /* FIXME: Validate the tag */
238 ExFreePool(Block);
239 }
240
241 /*
242 * @unimplemented
243 */
244 SIZE_T
245 STDCALL
246 ExQueryPoolBlockSize (
247 IN PVOID PoolBlock,
248 OUT PBOOLEAN QuotaCharged
249 )
250 {
251 UNIMPLEMENTED;
252 return FALSE;
253 }
254
255 /*
256 * @unimplemented
257 */
258 PVOID
259 STDCALL
260 MmAllocateMappingAddress (
261 IN SIZE_T NumberOfBytes,
262 IN ULONG PoolTag
263 )
264 {
265 UNIMPLEMENTED;
266 return 0;
267 }
268
269
270 /*
271 * @unimplemented
272 */
273 VOID
274 STDCALL
275 MmFreeMappingAddress (
276 IN PVOID BaseAddress,
277 IN ULONG PoolTag
278 )
279 {
280 UNIMPLEMENTED;
281 }
282
283 BOOLEAN
284 STDCALL
285 MiRaisePoolQuota(
286 IN POOL_TYPE PoolType,
287 IN ULONG CurrentMaxQuota,
288 OUT PULONG NewMaxQuota
289 )
290 {
291 /* Different quota raises depending on the type (64K vs 512K) */
292 if (PoolType == PagedPool) {
293
294 /* Make sure that 4MB is still left */
295 if ((MM_PAGED_POOL_SIZE >> 12) < ((MmPagedPoolSize + 4194304) >> 12)) {
296 return FALSE;
297 }
298
299 /* Increase Paged Pool Quota by 512K */
300 MmTotalPagedPoolQuota += 524288;
301 *NewMaxQuota = CurrentMaxQuota + 524288;
302 return TRUE;
303
304 } else { /* Nonpaged Pool */
305
306 /* Check if we still have 200 pages free*/
307 if (MmStats.NrFreePages < 200) return FALSE;
308
309 /* Check that 4MB is still left */
310 if ((MM_NONPAGED_POOL_SIZE >> 12) < ((MiNonPagedPoolLength + 4194304) >> 12)) {
311 return FALSE;
312 }
313
314 /* Increase Non Paged Pool Quota by 64K */
315 MmTotalNonPagedPoolQuota += 65536;
316 *NewMaxQuota = CurrentMaxQuota + 65536;
317 return TRUE;
318 }
319 }
320
321 /* EOF */