Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | /* * Copyright (c) 2015 Apple Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #ifndef __THRESHOLDS_H #define __THRESHOLDS_H /* * The actual threshold boundaries between allocators. These boundaries are * where the next allocator will take over and they are *inclusive* of the * limit value. That is, a TINY limit of X implies that an X-byte * allocation will come from TINY. * * The LARGE allocator cuts in at whatever the last boundary limit is. So, when * the medium allocator is compiled out, or not engaged, then large starts at * the limit of SMALL. */ #if MALLOC_TARGET_64BIT #define TINY_LIMIT_THRESHOLD (1008) #else // MALLOC_TARGET_64BIT #define TINY_LIMIT_THRESHOLD (496) #endif // MALLOC_TARGET_64BIT #if MALLOC_TARGET_IOS #define SMALL_LIMIT_THRESHOLD (15 * 1024) #else // MALLOC_TARGET_IOS #define SMALL_LIMIT_THRESHOLD (32 * 1024) #endif // MALLOC_TARGET_IOS #define MEDIUM_LIMIT_THRESHOLD (8 * 1024 * 1024) /* * Tiny region size definitions; these are split into quanta of 16 bytes, * 64504 blocks is the magical value of how many quanta we can fit in a 1mb * region including the region trailer and metadata. */ #define SHIFT_TINY_QUANTUM 4ull #define SHIFT_TINY_CEIL_BLOCKS 16 // ceil(log2(NUM_TINY_BLOCKS)) #define TINY_QUANTUM (1 << SHIFT_TINY_QUANTUM) #define NUM_TINY_BLOCKS 64504 #define NUM_TINY_CEIL_BLOCKS (1 << SHIFT_TINY_CEIL_BLOCKS) #define NUM_TINY_SLOTS (TINY_LIMIT_THRESHOLD >> SHIFT_TINY_QUANTUM) #if MALLOC_TARGET_64BIT #define TINY_BITMAP_RANGE_LIMIT 63 #else #define TINY_BITMAP_RANGE_LIMIT 31 #endif /* * Small region size definitions. * * We can only represent up to 1<<15 for msize; but we choose to stay * even below that to avoid the convention msize=0 => msize = (1<<15) */ #define SHIFT_SMALL_QUANTUM (SHIFT_TINY_QUANTUM + 5) // 9 #define SHIFT_SMALL_CEIL_BLOCKS 14 // ceil(log2(NUM_SMALL_BLOCKs)) #define SMALL_QUANTUM (1 << SHIFT_SMALL_QUANTUM) // 512 bytes #define SMALL_BLOCKS_ALIGN (SHIFT_SMALL_CEIL_BLOCKS + SHIFT_SMALL_QUANTUM) // 23 #define NUM_SMALL_BLOCKS 16319 #define NUM_SMALL_CEIL_BLOCKS (1 << SHIFT_SMALL_CEIL_BLOCKS) #define NUM_SMALL_SLOTS (SMALL_LIMIT_THRESHOLD >> SHIFT_SMALL_QUANTUM) /* * Medium region size definitions. * * We can only represent up to 1<<15 for msize; but we choose to stay * even below that to avoid the convention msize=0 => msize = (1<<15) */ #define SHIFT_MEDIUM_QUANTUM (SHIFT_SMALL_QUANTUM + 6) // 15 #define SHIFT_MEDIUM_CEIL_BLOCKS 12ull // ceil(log2(NUM_MEDIUM_BLOCKS)) #define MEDIUM_QUANTUM ((uint64_t)(1 << SHIFT_MEDIUM_QUANTUM)) // 32kbytes #define MEDIUM_BLOCKS_ALIGN (SHIFT_MEDIUM_CEIL_BLOCKS + SHIFT_MEDIUM_QUANTUM) // 27 #define NUM_MEDIUM_BLOCKS 4095 #define NUM_MEDIUM_CEIL_BLOCKS (1ull << SHIFT_MEDIUM_CEIL_BLOCKS) #define NUM_MEDIUM_SLOTS (MEDIUM_LIMIT_THRESHOLD >> SHIFT_MEDIUM_QUANTUM) #define MEDIUM_ACTIVATION_THRESHOLD (32ull * 1024 * 1024 * 1024) #define MEDIUM_CONDITIONAL_MADVISE_LIMIT (2 * 1024 * 1024) #define MEDIUM_MADVISE_SHIFT 4 #define MEDIUM_MADVISE_MIN ((3 * 1024 * 1024) / 2) // 1.5 megabytes /* * When performing a realloc() that must fallback to creating a new allocation * and copying the previous contents to the new allocation, vm_copy is used if * the allocation is greater than a given size. * * This threshold must be set such that all eligible allocations would have * come from a page-sized, page-aligned allocator (so, medium or large). * * Note: iOS disables this threshold because the VM forces non-sharing from * malloc-tagged allocations. */ #define VM_COPY_THRESHOLD (2 * 1024 * 1024) /* * <rdar://problem/6881926&27190324> Extremely old versions of Microsoft Word * (and, subsequently, versions of Adobe apps) required the Leopard behaviour * where LARGE allocations were zero-filled prior to returning them to the * caller. * * We've always used LARGE_THRESHOLD to denote this boundary but as we keep * moving it around it's better to fix it at the point it was originally. */ #define LEGACY_ZEROING_THRESHOLD (127 * 1024) /* * Large entry cache (death row) sizes. The large cache is bounded with * an overall top limit size, each entry is allowed a given slice of * that limit. */ #define LARGE_CACHE_EXPANDED_THRESHOLD (32ull * 1024 * 1024 * 1024) #if MALLOC_TARGET_64BIT #define LARGE_ENTRY_CACHE_SIZE_HIGH 64 #define LARGE_ENTRY_SIZE_ENTRY_LIMIT_HIGH (512 * 1024 * 1024) // lowmem config #define LARGE_ENTRY_CACHE_SIZE_LOW 16 #define LARGE_ENTRY_SIZE_ENTRY_LIMIT_LOW (128 * 1024 * 1024) #else // MALLOC_TARGET_64BIT #define LARGE_ENTRY_CACHE_SIZE_HIGH 8 #define LARGE_ENTRY_SIZE_ENTRY_LIMIT_HIGH (32 * 1024 * 1024) // lowmem config same as "highmem" #define LARGE_ENTRY_CACHE_SIZE_LOW LARGE_ENTRY_CACHE_SIZE_HIGH #define LARGE_ENTRY_SIZE_ENTRY_LIMIT_LOW LARGE_ENTRY_SIZE_ENTRY_LIMIT_HIGH #endif // MALLOC_TARGET_64BIT /* * Large entry cache (death row) "flotsam" limits. Until the large cache * contains at least "high" bytes, the cache is not cleaned under memory * pressure. After that, memory pressure notifications cause cache cleaning * until the large cache drops below the "low" limit. */ #define SZONE_FLOTSAM_THRESHOLD_LOW (1024 * 512) #define SZONE_FLOTSAM_THRESHOLD_HIGH (1024 * 1024) /* * The magazine freelist array must be large enough to accomodate the allocation * granularity of the tiny, small and medium allocators. In addition, the last * slot in the list is special and reserved for coalesced regions bigger than * the overall max allocation size of the allocator. */ #define MAGAZINE_FREELIST_SLOTS (NUM_MEDIUM_SLOTS + 1) #define MAGAZINE_FREELIST_BITMAP_WORDS ((MAGAZINE_FREELIST_SLOTS + 31) >> 5) /* * Density threshold used in determining the level of emptiness before * moving regions to the recirc depot. */ #define DENSITY_THRESHOLD(a) \ ((a) - ((a) >> 2)) // "Emptiness" f = 0.25, so "Density" is (1 - f)*a. Generally: ((a) - ((a) >> -log2(f))) /* * Minimum number of regions to retain in a recirc depot. */ #define DEFAULT_RECIRC_RETAINED_REGIONS 2 /* Sanity checks. */ // Tiny performs an ffsl of a uint64_t in order to determine how big an // allocation is. Therefore, the total allocation size of small cannot exceed // 63-bits worth of 16-byte quanta (64-bits but minus one for the start of the // allocation itself). MALLOC_STATIC_ASSERT((TINY_LIMIT_THRESHOLD / TINY_QUANTUM) <= TINY_BITMAP_RANGE_LIMIT, "TINY_LIMIT_THRESHOLD cannot exceed TINY_BITMAP_RANGE_LIMIT-bits worth of metadata"); // Check that the given threshold limits are a round multiple of their // allocator's quantum size. MALLOC_STATIC_ASSERT((TINY_LIMIT_THRESHOLD % TINY_QUANTUM) == 0, "TINY_LIMIT_THRESHOLD must be a multiple of TINY_QUANTUM"); MALLOC_STATIC_ASSERT((SMALL_LIMIT_THRESHOLD % SMALL_QUANTUM) == 0, "SMALL_LIMIT_THRESHOLD must be a multiple of SMALL_QUANTUM"); MALLOC_STATIC_ASSERT((MEDIUM_LIMIT_THRESHOLD % MEDIUM_QUANTUM) == 0, "MEDIUM_LIMIT_THRESHOLD must be a multiple of MEDIUM_QUANTUM"); // All the "slot" counts are calculated as a shift of thresholds now but // in-case someone decides to try hand-crafted values, make sure they adhere to // the basic expectation that slot count must account for all valid sizes of // allocations. MALLOC_STATIC_ASSERT(NUM_TINY_SLOTS >= TINY_LIMIT_THRESHOLD >> SHIFT_TINY_QUANTUM, "NUM_TINY_SLOTS must allow a free list for every valid TINY allocation"); MALLOC_STATIC_ASSERT(NUM_SMALL_SLOTS >= SMALL_LIMIT_THRESHOLD >> SHIFT_SMALL_QUANTUM, "NUM_SMALL_SLOTS must allow a free list for every valid SMALL allocation"); MALLOC_STATIC_ASSERT(NUM_MEDIUM_SLOTS >= MEDIUM_LIMIT_THRESHOLD >> SHIFT_MEDIUM_QUANTUM, "NUM_MEDIUM_SLOTS must allow a free list for every valid MEDIUM allocation"); // MAGAZINE_FREELIST_SLOTS cannot be dynamically selected by the MAX() of all // three allocators, so it must match (at least) the maxmium slot count of the // allocator with the largest range. // // Additionally, each allocator assumes that there is one additional free-list // slot above their maximum allocation size. This allows each allocator to // store an unordered list of maximally-sized free list entries. MALLOC_STATIC_ASSERT(NUM_TINY_SLOTS < MAGAZINE_FREELIST_SLOTS, "NUM_TINY_SLOTS must be less than MAGAZINE_FREELIST_SLOTS"); MALLOC_STATIC_ASSERT(NUM_SMALL_SLOTS < MAGAZINE_FREELIST_SLOTS, "NUM_SMALL_SLOTS must be less than MAGAZINE_FREELIST_SLOTS"); MALLOC_STATIC_ASSERT(NUM_MEDIUM_SLOTS < MAGAZINE_FREELIST_SLOTS, "NUM_MEDIUM_SLOTS must be less than MAGAZINE_FREELIST_SLOTS"); MALLOC_STATIC_ASSERT(VM_COPY_THRESHOLD >= SMALL_LIMIT_THRESHOLD, "VM_COPY_THRESHOLD must be larger than SMALL_LIMIT_THRESHOLD"); #endif // __THRESHOLDS_H |