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
);
164 _SEH_DEFINE_LOCALS(ExQuotaPoolVars
)
169 _SEH_FILTER(FreeAndGoOn
)
171 _SEH_ACCESS_LOCALS(ExQuotaPoolVars
);
173 /* Couldn't charge, so free the pool and let the caller SEH manage */
174 ExFreePool(_SEH_VAR(Block
));
175 return EXCEPTION_CONTINUE_SEARCH
;
183 ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType
,
184 IN ULONG NumberOfBytes
,
188 _SEH_DECLARE_LOCALS(ExQuotaPoolVars
);
190 /* Allocate the Pool First */
191 _SEH_VAR(Block
) = EiAllocatePool(PoolType
,
194 &ExAllocatePoolWithQuotaTag
);
196 /* "Quota is not charged to the thread for allocations >= PAGE_SIZE" - OSR Docs */
197 if (!(NumberOfBytes
>= PAGE_SIZE
))
199 /* Get the Current Process */
200 Process
= PsGetCurrentProcess();
202 /* PsChargePoolQuota returns an exception, so this needs SEH */
205 /* FIXME: Is there a way to get the actual Pool size allocated from the pool header? */
206 PsChargePoolQuota(Process
,
207 PoolType
& PAGED_POOL_MASK
,
210 _SEH_EXCEPT(FreeAndGoOn
)
212 /* Quota Exceeded and the caller had no SEH! */
213 KeBugCheck(STATUS_QUOTA_EXCEEDED
);
218 /* Return the allocated block */
219 return _SEH_VAR(Block
);
227 ExFreePool(IN PVOID Block
)
229 ASSERT_IRQL(DISPATCH_LEVEL
);
231 if (Block
>= MmPagedPoolBase
&& (char*)Block
< ((char*)MmPagedPoolBase
+ MmPagedPoolSize
))
233 ExFreePagedPool(Block
);
237 ExFreeNonPagedPool(Block
);
245 ExFreePoolWithTag(IN PVOID Block
, IN ULONG Tag
)
247 /* FIXME: Validate the tag */
256 ExQueryPoolBlockSize (
258 OUT PBOOLEAN QuotaCharged
270 MmAllocateMappingAddress (
271 IN SIZE_T NumberOfBytes
,
285 MmFreeMappingAddress (
286 IN PVOID BaseAddress
,
296 IN POOL_TYPE PoolType
,
297 IN ULONG CurrentMaxQuota
,
298 OUT PULONG NewMaxQuota
301 /* Different quota raises depending on the type (64K vs 512K) */
302 if (PoolType
== PagedPool
) {
304 /* Make sure that 4MB is still left */
305 if ((MM_PAGED_POOL_SIZE
>> 12) < ((MmPagedPoolSize
+ 4194304) >> 12)) {
309 /* Increase Paged Pool Quota by 512K */
310 MmTotalPagedPoolQuota
+= 524288;
311 *NewMaxQuota
= CurrentMaxQuota
+ 524288;
314 } else { /* Nonpaged Pool */
316 /* Check if we still have 200 pages free*/
317 if (MmStats
.NrFreePages
< 200) return FALSE
;
319 /* Check that 4MB is still left */
320 if ((MM_NONPAGED_POOL_SIZE
>> 12) < ((MiNonPagedPoolLength
+ 4194304) >> 12)) {
324 /* Increase Non Paged Pool Quota by 64K */
325 MmTotalNonPagedPoolQuota
+= 65536;
326 *NewMaxQuota
= CurrentMaxQuota
+ 65536;