00001 /*++ BUILD Version: 0001 // Increment this if a change has global effects 00002 00003 Copyright (c) 1989-1995 Microsoft Corporation 00004 00005 Module Name: 00006 00007 pool.h 00008 00009 Abstract: 00010 00011 Private executive data structures and procedure prototypes for pool 00012 allocation. 00013 00014 00015 There are three pool types: 00016 1. nonpaged, 00017 2. paged, and 00018 3. nonpagedmustsucceed. 00019 00020 There is only one of each the nonpaged and nonpagedmustsucceed pools. 00021 00022 There can be more than one paged pool. 00023 00024 Author: 00025 00026 Lou Perazzoli (loup) 23-Feb-1989 00027 00028 Revision History: 00029 00030 --*/ 00031 00032 #ifndef _POOL_ 00033 #define _POOL_ 00034 00035 #if !DBG && !defined (_WIN64) 00036 #define NO_POOL_CHECKS 1 00037 #endif 00038 00039 #define POOL_CACHE_SUPPORTED 0 00040 #define POOL_CACHE_ALIGN 0 00041 00042 #define NUMBER_OF_POOLS 3 00043 00044 #if defined(NT_UP) 00045 #define NUMBER_OF_PAGED_POOLS 2 00046 #else 00047 #define NUMBER_OF_PAGED_POOLS 4 00048 #endif 00049 00050 #define BASE_POOL_TYPE_MASK 1 00051 00052 #define MUST_SUCCEED_POOL_TYPE_MASK 2 00053 00054 #define CACHE_ALIGNED_POOL_TYPE_MASK 4 00055 00056 #define SESSION_POOL_MASK 32 00057 00058 #define POOL_VERIFIER_MASK 64 00059 00060 #define POOL_DRIVER_MASK 128 00061 00062 // 00063 // WARNING: POOL_QUOTA_MASK is overloaded by POOL_QUOTA_FAIL_INSTEAD_OF_RAISE 00064 // which is exported from ex.h. 00065 // 00066 // WARNING: POOL_RAISE_IF_ALLOCATION_FAILURE is exported from ex.h with a 00067 // value of 16. 00068 // 00069 // These definitions are used to control the raising of an exception as the 00070 // result of quota and allocation failures. 00071 // 00072 00073 #define POOL_QUOTA_MASK 8 00074 00075 #define POOL_TYPE_MASK (3) 00076 00077 //#define POOL_TYPE_AND_QUOTA_MASK (15) 00078 00079 // 00080 // Size of a pool page. 00081 // 00082 // This must be greater than or equal to the page size. 00083 // 00084 00085 #define POOL_PAGE_SIZE PAGE_SIZE 00086 00087 // 00088 // The smallest pool block size must be a multiple of the page size. 00089 // 00090 // Define the block size as 32. 00091 // 00092 00093 #if (PAGE_SIZE == 0x4000) 00094 #define POOL_BLOCK_SHIFT 6 00095 #else 00096 #define POOL_BLOCK_SHIFT 5 00097 #endif 00098 00099 #define POOL_LIST_HEADS (POOL_PAGE_SIZE / (1 << POOL_BLOCK_SHIFT)) 00100 00101 #define PAGE_ALIGNED(p) (!(((ULONG_PTR)p) & (POOL_PAGE_SIZE - 1))) 00102 00103 // 00104 // Define page end macro. 00105 // 00106 00107 #if defined(_ALPHA_) || defined(_IA64_) 00108 #define PAGE_END(Address) (((ULONG_PTR)(Address) & (PAGE_SIZE - 1)) == (PAGE_SIZE - (1 << POOL_BLOCK_SHIFT))) 00109 #else 00110 #define PAGE_END(Address) (((ULONG_PTR)(Address) & (PAGE_SIZE - 1)) == 0) 00111 #endif 00112 00113 // 00114 // Define pool descriptor structure. 00115 // 00116 00117 typedef struct _POOL_DESCRIPTOR { 00118 POOL_TYPE PoolType; 00119 ULONG PoolIndex; 00120 ULONG RunningAllocs; 00121 ULONG RunningDeAllocs; 00122 ULONG TotalPages; 00123 ULONG TotalBigPages; 00124 ULONG Threshold; 00125 PVOID LockAddress; 00126 LIST_ENTRY ListHeads[POOL_LIST_HEADS]; 00127 } POOL_DESCRIPTOR, *PPOOL_DESCRIPTOR; 00128 00129 // 00130 // Caveat Programmer: 00131 // 00132 // The pool header must be QWORD (8 byte) aligned in size. If it 00133 // is not, the pool allocation code will trash the allocated 00134 // buffer 00135 // 00136 // 00137 // 00138 // The layout of the pool header is: 00139 // 00140 // 31 23 16 15 7 0 00141 // +----------------------------------------------------------+ 00142 // | Current Size | PoolType+1 | Pool Index |Previous Size | 00143 // +----------------------------------------------------------+ 00144 // | ProcessBilled (NULL if not allocated with quota) | 00145 // +----------------------------------------------------------+ 00146 // | Zero or more longwords of pad such that the pool header | 00147 // | is on a cache line boundary and the pool body is also | 00148 // | on a cache line boundary. | 00149 // +----------------------------------------------------------+ 00150 // 00151 // PoolBody: 00152 // 00153 // +----------------------------------------------------------+ 00154 // | Used by allocator, or when free FLINK into sized list | 00155 // +----------------------------------------------------------+ 00156 // | Used by allocator, or when free BLINK into sized list | 00157 // +----------------------------------------------------------+ 00158 // ... rest of pool block... 00159 // 00160 // 00161 // N.B. The size fields of the pool header are expressed in units of the 00162 // smallest pool block size. 00163 // 00164 00165 typedef struct _POOL_HEADER { 00166 union { 00167 struct { 00168 UCHAR PreviousSize; 00169 UCHAR PoolIndex; 00170 UCHAR PoolType; 00171 UCHAR BlockSize; 00172 }; 00173 ULONG Ulong1; // used for InterlockedCompareExchange required by Alpha 00174 }; 00175 #ifdef _WIN64 00176 ULONG PoolTag; 00177 #endif 00178 union { 00179 EPROCESS *ProcessBilled; 00180 #ifndef _WIN64 00181 ULONG PoolTag; 00182 #endif 00183 struct { 00184 USHORT AllocatorBackTraceIndex; 00185 USHORT PoolTagHash; 00186 }; 00187 }; 00188 } POOL_HEADER, *PPOOL_HEADER; 00189 00190 // 00191 // Define size of pool block overhead. 00192 // 00193 00194 #define POOL_OVERHEAD ((LONG)sizeof(POOL_HEADER)) 00195 00196 // 00197 // Define size of pool block overhead when the block is on a freelist. 00198 // 00199 00200 #define POOL_FREE_BLOCK_OVERHEAD (POOL_OVERHEAD + sizeof (LIST_ENTRY)) 00201 00202 // 00203 // Define dummy type so computation of pointers is simplified. 00204 // 00205 00206 typedef struct _POOL_BLOCK { 00207 UCHAR Fill[1 << POOL_BLOCK_SHIFT]; 00208 } POOL_BLOCK, *PPOOL_BLOCK; 00209 00210 // 00211 // Define size of smallest pool block. 00212 // 00213 00214 #define POOL_SMALLEST_BLOCK (sizeof(POOL_BLOCK)) 00215 00216 // 00217 // Define pool tracking information. 00218 // 00219 00220 #define POOL_BACKTRACEINDEX_PRESENT 0x8000 00221 00222 #if POOL_CACHE_SUPPORTED 00223 #define POOL_BUDDY_MAX PoolBuddyMax 00224 #else 00225 #define POOL_BUDDY_MAX \ 00226 (POOL_PAGE_SIZE - (POOL_OVERHEAD + POOL_SMALLEST_BLOCK )) 00227 #endif //POOL_CACHE_SUPPORTED 00228 00229 // 00230 // Pool support routine and macro not for general consumption. 00231 // This is only used by the memory manager. 00232 // 00233 00234 VOID 00235 ExpInitializePoolDescriptor( 00236 IN PPOOL_DESCRIPTOR PoolDescriptor, 00237 IN POOL_TYPE PoolType, 00238 IN ULONG PoolIndex, 00239 IN ULONG Threshold, 00240 IN PVOID PoolLock 00241 ); 00242 00243 //++ 00244 //SIZE_T 00245 //EX_REAL_POOL_USAGE ( 00246 // IN SIZE_T SizeInBytes 00247 // ); 00248 // 00249 // Routine Description: 00250 // 00251 // This routine determines the real pool cost of the supplied allocation. 00252 // 00253 // Arguments 00254 // 00255 // SizeInBytes - Supplies the allocation size in bytes. 00256 // 00257 // Return Value: 00258 // 00259 // TRUE if unused segment trimming should be initiated, FALSE if not. 00260 // 00261 //-- 00262 00263 #define EX_REAL_POOL_USAGE(SizeInBytes) \ 00264 (((SizeInBytes) > POOL_BUDDY_MAX) ? \ 00265 (ROUND_TO_PAGES(SizeInBytes)) : \ 00266 (((SizeInBytes) + POOL_OVERHEAD + (POOL_SMALLEST_BLOCK - 1)) & ~(POOL_SMALLEST_BLOCK - 1))) 00267 00268 typedef struct _POOL_TRACKER_TABLE { 00269 ULONG Key; 00270 ULONG NonPagedAllocs; 00271 ULONG NonPagedFrees; 00272 SIZE_T NonPagedBytes; 00273 ULONG PagedAllocs; 00274 ULONG PagedFrees; 00275 SIZE_T PagedBytes; 00276 } POOL_TRACKER_TABLE, *PPOOL_TRACKER_TABLE; 00277 00278 // 00279 // N.B. The last entry of the pool tracker table is used for all overflow 00280 // table entries. 00281 // 00282 00283 extern PPOOL_TRACKER_TABLE PoolTrackTable; 00284 00285 typedef struct _POOL_TRACKER_BIG_PAGES { 00286 PVOID Va; 00287 ULONG Key; 00288 ULONG NumberOfPages; 00289 } POOL_TRACKER_BIG_PAGES, *PPOOL_TRACKER_BIG_PAGES; 00290 00291 #endif