1 /* $Id: pool.c,v 1.36 2004/12/11 00:13:37 royce Exp $
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 ****************************************************************/
16 #include <internal/debug.h>
18 extern ULONG MiNonPagedPoolLength
;
19 extern ULONG MmTotalPagedPoolQuota
;
20 extern ULONG MmTotalNonPagedPoolQuota
;
21 extern MM_STATS MmStats
;
23 /* GLOBALS *****************************************************************/
25 #define TAG_NONE (ULONG)(('N'<<0) + ('o'<<8) + ('n'<<16) + ('e'<<24))
28 ExRosQueryPagedPoolTag ( PVOID Block
);
30 /* FUNCTIONS ***************************************************************/
33 EiAllocatePool(POOL_TYPE PoolType
,
44 case NonPagedPoolMustSucceed
:
45 case NonPagedPoolCacheAligned
:
46 case NonPagedPoolCacheAlignedMustS
:
48 ExAllocateNonPagedPoolWithTag(PoolType
,
55 case PagedPoolCacheAligned
:
56 Block
= ExAllocatePagedPoolWithTag(PoolType
,NumberOfBytes
,Tag
);
63 if ((PoolType
==NonPagedPoolMustSucceed
||
64 PoolType
==NonPagedPoolCacheAlignedMustS
) && Block
==NULL
)
66 KEBUGCHECK(MUST_SUCCEED_POOL_EMPTY
);
75 ExAllocatePool (POOL_TYPE PoolType
, ULONG NumberOfBytes
)
77 * FUNCTION: Allocates pool memory of a specified type and returns a pointer
78 * to the allocated block. This routine is used for general purpose allocation
82 * Specifies the type of memory to allocate which can be one
86 * NonPagedPoolMustSucceed
87 * NonPagedPoolCacheAligned
88 * NonPagedPoolCacheAlignedMustS
90 * PagedPoolCacheAligned
93 * Specifies the number of bytes to allocate
94 * RETURNS: The allocated block on success
100 #if defined(__GNUC__)
102 Block
= EiAllocatePool(PoolType
,
105 (PVOID
)__builtin_return_address(0));
106 #elif defined(_MSC_VER)
108 Block
= EiAllocatePool(PoolType
,
113 #error Unknown compiler
124 ExAllocatePoolWithTag (ULONG PoolType
, ULONG NumberOfBytes
, ULONG Tag
)
128 #if defined(__GNUC__)
130 Block
= EiAllocatePool(PoolType
,
133 (PVOID
)__builtin_return_address(0));
134 #elif defined(_MSC_VER)
136 Block
= EiAllocatePool(PoolType
,
139 &ExAllocatePoolWithTag
);
141 #error Unknown compiler
152 ExAllocatePoolWithQuota (POOL_TYPE PoolType
, ULONG NumberOfBytes
)
154 return(ExAllocatePoolWithQuotaTag(PoolType
, NumberOfBytes
, TAG_NONE
));
162 ExAllocatePoolWithTagPriority(
163 IN POOL_TYPE PoolType
,
164 IN SIZE_T NumberOfBytes
,
166 IN EX_POOL_PRIORITY Priority
169 /* Check if this is one of the "Special" Flags, used by the Verifier */
171 /* Check if this is a xxSpecialUnderrun */
173 return MiAllocateSpecialPool(PoolType
, NumberOfBytes
, Tag
, 1);
174 } else { /* xxSpecialOverrun */
175 return MiAllocateSpecialPool(PoolType
, NumberOfBytes
, Tag
, 0);
179 /* FIXME: Do Ressource Checking Based on Priority and fail if resources too low*/
181 /* Do the allocation */
182 return ExAllocatePoolWithTag(PoolType
, NumberOfBytes
, Tag
);
189 ExAllocatePoolWithQuotaTag (IN POOL_TYPE PoolType
,
190 IN ULONG NumberOfBytes
,
196 /* Allocate the Pool First */
197 Block
= EiAllocatePool(PoolType
,
200 &ExAllocatePoolWithQuotaTag
);
202 /* "Quota is not charged to the thread for allocations >= PAGE_SIZE" - OSR Docs */
203 if (!(NumberOfBytes
>= PAGE_SIZE
)) {
205 /* Get the Current Process */
206 Process
= PsGetCurrentProcess();
208 /* PsChargePoolQuota returns an exception, so this needs SEH */
209 #if defined(__GNUC__)
210 _SEH_FILTER(FreeAndGoOn
) {
211 /* Couldn't charge, so free the pool and let the caller SEH manage */
213 return EXCEPTION_CONTINUE_SEARCH
;
214 } _SEH_TRY_FILTER(FreeAndGoOn
) {
215 //* FIXME: Is there a way to get the actual Pool size allocated from the pool header? */
216 PsChargePoolQuota(Process
, PoolType
, NumberOfBytes
);
218 /* Quota Exceeded and the caller had no SEH! */
219 KeBugCheck(STATUS_QUOTA_EXCEEDED
);
221 #else /* assuming all other Win32 compilers understand SEH */
223 PsChargePoolQuota(Process
, PoolType
, NumberOfBytes
);
225 __except (ExFreePool(Block
), EXCEPTION_CONTINUE_SEARCH
) {
226 KeBugCheck(STATUS_QUOTA_EXCEEDED
);
238 ExFreePool(IN PVOID Block
)
240 ASSERT_IRQL(DISPATCH_LEVEL
);
242 if (Block
>= MmPagedPoolBase
&& (char*)Block
< ((char*)MmPagedPoolBase
+ MmPagedPoolSize
))
244 ExFreePagedPool(Block
);
248 ExFreeNonPagedPool(Block
);
256 ExFreePoolWithTag(IN PVOID Block
, IN ULONG Tag
)
258 /* FIXME: Validate the tag */
267 ExQueryPoolBlockSize (
269 OUT PBOOLEAN QuotaCharged
281 MmAllocateMappingAddress (
282 IN SIZE_T NumberOfBytes
,
296 MmFreeMappingAddress (
297 IN PVOID BaseAddress
,
307 IN POOL_TYPE PoolType
,
308 IN ULONG CurrentMaxQuota
,
309 OUT PULONG NewMaxQuota
312 /* Different quota raises depending on the type (64K vs 512K) */
313 if (PoolType
== PagedPool
) {
315 /* Make sure that 4MB is still left */
316 if ((MM_PAGED_POOL_SIZE
>> 12) < ((MmPagedPoolSize
+ 4194304) >> 12)) {
320 /* Increase Paged Pool Quota by 512K */
321 MmTotalPagedPoolQuota
+= 524288;
322 *NewMaxQuota
= CurrentMaxQuota
+ 524288;
325 } else { /* Nonpaged Pool */
327 /* Check if we still have 200 pages free*/
328 if (MmStats
.NrFreePages
< 200) return FALSE
;
330 /* Check that 4MB is still left */
331 if ((MM_NONPAGED_POOL_SIZE
>> 12) < ((MiNonPagedPoolLength
+ 4194304) >> 12)) {
335 /* Increase Non Paged Pool Quota by 64K */
336 MmTotalNonPagedPoolQuota
+= 65536;
337 *NewMaxQuota
= CurrentMaxQuota
+ 65536;
343 ExRosQueryPoolTag ( PVOID Block
)
345 ASSERT_IRQL(DISPATCH_LEVEL
);
347 if (Block
>= MmPagedPoolBase
&& (char*)Block
< ((char*)MmPagedPoolBase
+ MmPagedPoolSize
))
349 return ExRosQueryPagedPoolTag(Block
);