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 * PROGRAMMER: David Welch (welch@mcmail.com)
10 /* INCLUDES ****************************************************************/
15 #include <internal/debug.h>
17 extern ULONG MiNonPagedPoolLength
;
18 extern ULONG MmTotalPagedPoolQuota
;
19 extern ULONG MmTotalNonPagedPoolQuota
;
20 extern MM_STATS MmStats
;
22 /* GLOBALS *****************************************************************/
24 #define TAG_NONE (ULONG)(('N'<<0) + ('o'<<8) + ('n'<<16) + ('e'<<24))
27 ExRosQueryPagedPoolTag ( PVOID Block
);
29 /* FUNCTIONS ***************************************************************/
32 EiAllocatePool(POOL_TYPE PoolType
,
43 case NonPagedPoolMustSucceed
:
44 case NonPagedPoolCacheAligned
:
45 case NonPagedPoolCacheAlignedMustS
:
47 ExAllocateNonPagedPoolWithTag(PoolType
,
54 case PagedPoolCacheAligned
:
55 Block
= ExAllocatePagedPoolWithTag(PoolType
,NumberOfBytes
,Tag
);
62 if ((PoolType
==NonPagedPoolMustSucceed
||
63 PoolType
==NonPagedPoolCacheAlignedMustS
) && Block
==NULL
)
65 KEBUGCHECK(MUST_SUCCEED_POOL_EMPTY
);
74 ExAllocatePool (POOL_TYPE PoolType
, ULONG NumberOfBytes
)
76 * FUNCTION: Allocates pool memory of a specified type and returns a pointer
77 * to the allocated block. This routine is used for general purpose allocation
81 * Specifies the type of memory to allocate which can be one
85 * NonPagedPoolMustSucceed
86 * NonPagedPoolCacheAligned
87 * NonPagedPoolCacheAlignedMustS
89 * PagedPoolCacheAligned
92 * Specifies the number of bytes to allocate
93 * RETURNS: The allocated block on success
101 Block
= EiAllocatePool(PoolType
,
104 (PVOID
)__builtin_return_address(0));
105 #elif defined(_MSC_VER)
107 Block
= EiAllocatePool(PoolType
,
112 #error Unknown compiler
123 ExAllocatePoolWithTag (POOL_TYPE PoolType
, ULONG NumberOfBytes
, ULONG Tag
)
127 #if defined(__GNUC__)
129 Block
= EiAllocatePool(PoolType
,
132 (PVOID
)__builtin_return_address(0));
133 #elif defined(_MSC_VER)
135 Block
= EiAllocatePool(PoolType
,
138 &ExAllocatePoolWithTag
);
140 #error Unknown compiler
151 ExAllocatePoolWithQuota (POOL_TYPE PoolType
, ULONG NumberOfBytes
)
153 return(ExAllocatePoolWithQuotaTag(PoolType
, NumberOfBytes
, TAG_NONE
));
161 ExAllocatePoolWithTagPriority(
162 IN POOL_TYPE PoolType
,
163 IN SIZE_T NumberOfBytes
,
165 IN EX_POOL_PRIORITY Priority
168 /* Check if this is one of the "Special" Flags, used by the Verifier */
170 /* Check if this is a xxSpecialUnderrun */
172 return MiAllocateSpecialPool(PoolType
, NumberOfBytes
, Tag
, 1);
173 } else { /* xxSpecialOverrun */
174 return MiAllocateSpecialPool(PoolType
, NumberOfBytes
, Tag
, 0);
178 /* FIXME: Do Ressource Checking Based on Priority and fail if resources too low*/
180 /* Do the allocation */
181 return ExAllocatePoolWithTag(PoolType
, NumberOfBytes
, Tag
);
188 ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType
,
189 IN ULONG NumberOfBytes
,
195 /* Allocate the Pool First */
196 Block
= EiAllocatePool(PoolType
,
199 &ExAllocatePoolWithQuotaTag
);
201 /* "Quota is not charged to the thread for allocations >= PAGE_SIZE" - OSR Docs */
202 if (!(NumberOfBytes
>= PAGE_SIZE
)) {
204 /* Get the Current Process */
205 Process
= PsGetCurrentProcess();
207 /* PsChargePoolQuota returns an exception, so this needs SEH */
208 #if defined(__GNUC__)
209 _SEH_FILTER(FreeAndGoOn
) {
210 /* Couldn't charge, so free the pool and let the caller SEH manage */
212 return EXCEPTION_CONTINUE_SEARCH
;
213 } _SEH_TRY_FILTER(FreeAndGoOn
) {
214 //* FIXME: Is there a way to get the actual Pool size allocated from the pool header? */
215 PsChargePoolQuota(Process
, PoolType
, NumberOfBytes
);
217 /* Quota Exceeded and the caller had no SEH! */
218 KeBugCheck(STATUS_QUOTA_EXCEEDED
);
220 #else /* assuming all other Win32 compilers understand SEH */
222 PsChargePoolQuota(Process
, PoolType
, NumberOfBytes
);
224 __except (ExFreePool(Block
), EXCEPTION_CONTINUE_SEARCH
) {
225 KeBugCheck(STATUS_QUOTA_EXCEEDED
);
237 ExFreePool(IN PVOID Block
)
239 ASSERT_IRQL(DISPATCH_LEVEL
);
241 if (Block
>= MmPagedPoolBase
&& (char*)Block
< ((char*)MmPagedPoolBase
+ MmPagedPoolSize
))
243 ExFreePagedPool(Block
);
247 ExFreeNonPagedPool(Block
);
255 ExFreePoolWithTag(IN PVOID Block
, IN ULONG Tag
)
257 /* FIXME: Validate the tag */
266 ExQueryPoolBlockSize (
268 OUT PBOOLEAN QuotaCharged
280 MmAllocateMappingAddress (
281 IN SIZE_T NumberOfBytes
,
295 MmFreeMappingAddress (
296 IN PVOID BaseAddress
,
306 IN POOL_TYPE PoolType
,
307 IN ULONG CurrentMaxQuota
,
308 OUT PULONG NewMaxQuota
311 /* Different quota raises depending on the type (64K vs 512K) */
312 if (PoolType
== PagedPool
) {
314 /* Make sure that 4MB is still left */
315 if ((MM_PAGED_POOL_SIZE
>> 12) < ((MmPagedPoolSize
+ 4194304) >> 12)) {
319 /* Increase Paged Pool Quota by 512K */
320 MmTotalPagedPoolQuota
+= 524288;
321 *NewMaxQuota
= CurrentMaxQuota
+ 524288;
324 } else { /* Nonpaged Pool */
326 /* Check if we still have 200 pages free*/
327 if (MmStats
.NrFreePages
< 200) return FALSE
;
329 /* Check that 4MB is still left */
330 if ((MM_NONPAGED_POOL_SIZE
>> 12) < ((MiNonPagedPoolLength
+ 4194304) >> 12)) {
334 /* Increase Non Paged Pool Quota by 64K */
335 MmTotalNonPagedPoolQuota
+= 65536;
336 *NewMaxQuota
= CurrentMaxQuota
+ 65536;
342 ExRosQueryPoolTag ( PVOID Block
)
344 ASSERT_IRQL(DISPATCH_LEVEL
);
346 if (Block
>= MmPagedPoolBase
&& (char*)Block
< ((char*)MmPagedPoolBase
+ MmPagedPoolSize
))
348 return ExRosQueryPagedPoolTag(Block
);