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
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
11 /* INCLUDES ****************************************************************/
16 #include <internal/debug.h>
18 extern ULONG MiNonPagedPoolLength
;
19 extern ULONG MmTotalPagedPoolQuota
;
20 extern ULONG MmTotalNonPagedPoolQuota
;
21 extern MM_STATS MmStats
;
23 /* FUNCTIONS ***************************************************************/
26 EiAllocatePool(POOL_TYPE PoolType
,
33 /* FIXME: Handle SESSION_POOL_MASK, VERIFIER_POOL_MASK, QUOTA_POOL_MASK */
34 if (PoolType
& PAGED_POOL_MASK
)
36 Block
= ExAllocatePagedPoolWithTag(PoolType
,NumberOfBytes
,Tag
);
40 Block
= ExAllocateNonPagedPoolWithTag(PoolType
,NumberOfBytes
,Tag
,Caller
);
43 if ((PoolType
& MUST_SUCCEED_POOL_MASK
) && Block
==NULL
)
45 KEBUGCHECK(MUST_SUCCEED_POOL_EMPTY
);
54 ExAllocatePool (POOL_TYPE PoolType
, ULONG NumberOfBytes
)
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
61 * Specifies the type of memory to allocate which can be one
65 * NonPagedPoolMustSucceed
66 * NonPagedPoolCacheAligned
67 * NonPagedPoolCacheAlignedMustS
69 * PagedPoolCacheAligned
72 * Specifies the number of bytes to allocate
73 * RETURNS: The allocated block on success
81 Block
= EiAllocatePool(PoolType
,
84 (PVOID
)__builtin_return_address(0));
85 #elif defined(_MSC_VER)
87 Block
= EiAllocatePool(PoolType
,
92 #error Unknown compiler
103 ExAllocatePoolWithTag (POOL_TYPE PoolType
, ULONG NumberOfBytes
, ULONG Tag
)
107 #if defined(__GNUC__)
109 Block
= EiAllocatePool(PoolType
,
112 (PVOID
)__builtin_return_address(0));
113 #elif defined(_MSC_VER)
115 Block
= EiAllocatePool(PoolType
,
118 &ExAllocatePoolWithTag
);
120 #error Unknown compiler
131 ExAllocatePoolWithQuota (POOL_TYPE PoolType
, ULONG NumberOfBytes
)
133 return(ExAllocatePoolWithQuotaTag(PoolType
, NumberOfBytes
, TAG_NONE
));
141 ExAllocatePoolWithTagPriority(
142 IN POOL_TYPE PoolType
,
143 IN SIZE_T NumberOfBytes
,
145 IN EX_POOL_PRIORITY Priority
148 /* Check if this is one of the "Special" Flags, used by the Verifier */
150 /* Check if this is a xxSpecialUnderrun */
152 return MiAllocateSpecialPool(PoolType
, NumberOfBytes
, Tag
, 1);
153 } else { /* xxSpecialOverrun */
154 return MiAllocateSpecialPool(PoolType
, NumberOfBytes
, Tag
, 0);
158 /* FIXME: Do Ressource Checking Based on Priority and fail if resources too low*/
160 /* Do the allocation */
161 return ExAllocatePoolWithTag(PoolType
, NumberOfBytes
, Tag
);
168 ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType
,
169 IN ULONG NumberOfBytes
,
175 /* Allocate the Pool First */
176 Block
= EiAllocatePool(PoolType
,
179 &ExAllocatePoolWithQuotaTag
);
181 /* "Quota is not charged to the thread for allocations >= PAGE_SIZE" - OSR Docs */
182 if (!(NumberOfBytes
>= PAGE_SIZE
)) {
184 /* Get the Current Process */
185 Process
= PsGetCurrentProcess();
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 */
192 return EXCEPTION_CONTINUE_SEARCH
;
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
);
200 #else /* assuming all other Win32 compilers understand SEH */
202 PsChargePoolQuota(Process
, PoolType
& PAGED_POOL_MASK
, NumberOfBytes
);
204 __except (ExFreePool(Block
), EXCEPTION_CONTINUE_SEARCH
) {
205 KeBugCheck(STATUS_QUOTA_EXCEEDED
);
217 ExFreePool(IN PVOID Block
)
219 ASSERT_IRQL(DISPATCH_LEVEL
);
221 if (Block
>= MmPagedPoolBase
&& (char*)Block
< ((char*)MmPagedPoolBase
+ MmPagedPoolSize
))
223 ExFreePagedPool(Block
);
227 ExFreeNonPagedPool(Block
);
235 ExFreePoolWithTag(IN PVOID Block
, IN ULONG Tag
)
237 /* FIXME: Validate the tag */
246 ExQueryPoolBlockSize (
248 OUT PBOOLEAN QuotaCharged
260 MmAllocateMappingAddress (
261 IN SIZE_T NumberOfBytes
,
275 MmFreeMappingAddress (
276 IN PVOID BaseAddress
,
286 IN POOL_TYPE PoolType
,
287 IN ULONG CurrentMaxQuota
,
288 OUT PULONG NewMaxQuota
291 /* Different quota raises depending on the type (64K vs 512K) */
292 if (PoolType
== PagedPool
) {
294 /* Make sure that 4MB is still left */
295 if ((MM_PAGED_POOL_SIZE
>> 12) < ((MmPagedPoolSize
+ 4194304) >> 12)) {
299 /* Increase Paged Pool Quota by 512K */
300 MmTotalPagedPoolQuota
+= 524288;
301 *NewMaxQuota
= CurrentMaxQuota
+ 524288;
304 } else { /* Nonpaged Pool */
306 /* Check if we still have 200 pages free*/
307 if (MmStats
.NrFreePages
< 200) return FALSE
;
309 /* Check that 4MB is still left */
310 if ((MM_NONPAGED_POOL_SIZE
>> 12) < ((MiNonPagedPoolLength
+ 4194304) >> 12)) {
314 /* Increase Non Paged Pool Quota by 64K */
315 MmTotalNonPagedPoolQuota
+= 65536;
316 *NewMaxQuota
= CurrentMaxQuota
+ 65536;