arena.c revision 41631d00618d7262125e501c91d31b4d70e605fa
1e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define JEMALLOC_ARENA_C_ 2b0fd5016db74678476868abb380170b319a50480Jason Evans#include "internal/jemalloc_internal.h" 3e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 4e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/ 5e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Data. */ 6e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 7e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t opt_lg_qspace_max = LG_QSPACE_MAX_DEFAULT; 8e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t opt_lg_cspace_max = LG_CSPACE_MAX_DEFAULT; 9e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t opt_lg_medium_max = LG_MEDIUM_MAX_DEFAULT; 10e476f8a161d445211fd6e54fe370275196e66bcbJason Evansssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT; 11e476f8a161d445211fd6e54fe370275196e66bcbJason Evansuint8_t const *small_size2bin; 12e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 13e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Various bin-related settings. */ 14e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned nqbins; 15e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned ncbins; 16e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned nsbins; 17e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned nmbins; 18e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned nbins; 19e476f8a161d445211fd6e54fe370275196e66bcbJason Evansunsigned mbin0; 20e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t qspace_max; 21e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t cspace_min; 22e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t cspace_max; 23e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t sspace_min; 24e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t sspace_max; 25e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t medium_max; 26e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 27e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t lg_mspace; 28e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t mspace_mask; 29e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 30e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 31e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * const_small_size2bin is a static constant lookup table that in the common 32e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * case can be used as-is for small_size2bin. For dynamically linked programs, 33e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * this avoids a page of memory overhead per process. 34e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 35e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_1(i) i, 36e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_2(i) S2B_1(i) S2B_1(i) 37e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_4(i) S2B_2(i) S2B_2(i) 38e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_8(i) S2B_4(i) S2B_4(i) 39e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_16(i) S2B_8(i) S2B_8(i) 40e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_32(i) S2B_16(i) S2B_16(i) 41e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_64(i) S2B_32(i) S2B_32(i) 42e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_128(i) S2B_64(i) S2B_64(i) 43e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_256(i) S2B_128(i) S2B_128(i) 44e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 45e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * The number of elements in const_small_size2bin is dependent on page size 46e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * and on the definition for SUBPAGE. If SUBPAGE changes, the '- 255' must also 47e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * change, along with the addition/removal of static lookup table element 48e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * definitions. 49e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 50e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic const uint8_t const_small_size2bin[STATIC_PAGE_SIZE - 255] = { 51e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_1(0xffU) /* 0 */ 52e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#if (LG_QUANTUM == 4) 53e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 64-bit system ************************/ 54e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# ifdef JEMALLOC_TINY 55e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_2(0) /* 2 */ 56e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_2(1) /* 4 */ 57e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_4(2) /* 8 */ 58e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(3) /* 16 */ 59e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# define S2B_QMIN 3 60e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# else 61e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_16(0) /* 16 */ 62e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# define S2B_QMIN 0 63e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# endif 64e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_16(S2B_QMIN + 1) /* 32 */ 65e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_16(S2B_QMIN + 2) /* 48 */ 66e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_16(S2B_QMIN + 3) /* 64 */ 67e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_16(S2B_QMIN + 4) /* 80 */ 68e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_16(S2B_QMIN + 5) /* 96 */ 69e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_16(S2B_QMIN + 6) /* 112 */ 70e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_16(S2B_QMIN + 7) /* 128 */ 71e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# define S2B_CMIN (S2B_QMIN + 8) 72e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#else 73e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 32-bit system ************************/ 74e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# ifdef JEMALLOC_TINY 75e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_2(0) /* 2 */ 76e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_2(1) /* 4 */ 77e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_4(2) /* 8 */ 78e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# define S2B_QMIN 2 79e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# else 80e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(0) /* 8 */ 81e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# define S2B_QMIN 0 82e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# endif 83e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 1) /* 16 */ 84e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 2) /* 24 */ 85e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 3) /* 32 */ 86e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 4) /* 40 */ 87e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 5) /* 48 */ 88e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 6) /* 56 */ 89e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 7) /* 64 */ 90e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 8) /* 72 */ 91e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 9) /* 80 */ 92e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 10) /* 88 */ 93e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 11) /* 96 */ 94e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 12) /* 104 */ 95e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 13) /* 112 */ 96e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 14) /* 120 */ 97e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_8(S2B_QMIN + 15) /* 128 */ 98e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# define S2B_CMIN (S2B_QMIN + 16) 99e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 100e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/****************************************/ 101e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_64(S2B_CMIN + 0) /* 192 */ 102e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_64(S2B_CMIN + 1) /* 256 */ 103e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_64(S2B_CMIN + 2) /* 320 */ 104e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_64(S2B_CMIN + 3) /* 384 */ 105e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_64(S2B_CMIN + 4) /* 448 */ 106e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_64(S2B_CMIN + 5) /* 512 */ 107e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# define S2B_SMIN (S2B_CMIN + 6) 108e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 0) /* 768 */ 109e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 1) /* 1024 */ 110e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 2) /* 1280 */ 111e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 3) /* 1536 */ 112e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 4) /* 1792 */ 113e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 5) /* 2048 */ 114e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 6) /* 2304 */ 115e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 7) /* 2560 */ 116e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 8) /* 2816 */ 117e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 9) /* 3072 */ 118e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 10) /* 3328 */ 119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 11) /* 3584 */ 120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 12) /* 3840 */ 121e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#if (STATIC_PAGE_SHIFT == 13) 122e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 13) /* 4096 */ 123e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 14) /* 4352 */ 124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 15) /* 4608 */ 125e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 16) /* 4864 */ 126e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 17) /* 5120 */ 127e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 18) /* 5376 */ 128e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 19) /* 5632 */ 129e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 20) /* 5888 */ 130e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 21) /* 6144 */ 131e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 22) /* 6400 */ 132e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 23) /* 6656 */ 133e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 24) /* 6912 */ 134e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 25) /* 7168 */ 135e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 26) /* 7424 */ 136e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 27) /* 7680 */ 137e476f8a161d445211fd6e54fe370275196e66bcbJason Evans S2B_256(S2B_SMIN + 28) /* 7936 */ 138e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 139e476f8a161d445211fd6e54fe370275196e66bcbJason Evans}; 140e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_1 141e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_2 142e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_4 143e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_8 144e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_16 145e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_32 146e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_64 147e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_128 148e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_256 149e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_QMIN 150e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_CMIN 151e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_SMIN 152e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 153e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/ 154e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Function prototypes for non-inline static functions. */ 155e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 156e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_run_split(arena_t *arena, arena_run_t *run, size_t size, 157e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool large, bool zero); 158e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_chunk_t *arena_chunk_alloc(arena_t *arena); 159e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk); 160e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool large, 161e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool zero); 162e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_purge(arena_t *arena); 163e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty); 164e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, 165e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run, size_t oldsize, size_t newsize); 166e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, 167e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run, size_t oldsize, size_t newsize, bool dirty); 168e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin); 169e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin); 170e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic size_t arena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size); 171e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void *arena_malloc_large(arena_t *arena, size_t size, bool zero); 172e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool arena_is_large(const void *ptr); 173e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, 174e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run, arena_bin_t *bin); 175b34e8684ec025aa780997c11f847c19fb269755bJason Evans#ifdef JEMALLOC_STATS 176b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void arena_stats_aprint(size_t nactive, size_t ndirty, 177b34e8684ec025aa780997c11f847c19fb269755bJason Evans const arena_stats_t *astats, 178ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans void (*write4)(void *, const char *, const char *, const char *, 179ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans const char *), void *w4opaque); 180b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void arena_stats_bprint(arena_t *arena, 181b34e8684ec025aa780997c11f847c19fb269755bJason Evans const malloc_bin_stats_t *bstats, 182ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans void (*write4)(void *, const char *, const char *, const char *, 183ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans const char *), void *w4opaque); 184b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void arena_stats_lprint(const malloc_large_stats_t *lstats, 185ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans void (*write4)(void *, const char *, const char *, const char *, 186ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans const char *), void *w4opaque); 187b34e8684ec025aa780997c11f847c19fb269755bJason Evans#endif 188e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, 189e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ptr, size_t size, size_t oldsize); 190e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, 191e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ptr, size_t size, size_t oldsize); 192e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool arena_ralloc_large(void *ptr, size_t size, size_t oldsize); 193e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY 194e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic size_t pow2_ceil(size_t x); 195e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 196e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool small_size2bin_init(void); 197e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG 198e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void small_size2bin_validate(void); 199e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 200e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool small_size2bin_init_hard(void); 201e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 202e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/ 203e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 204e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int 205e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_comp(arena_chunk_t *a, arena_chunk_t *b) 206e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 207e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uintptr_t a_chunk = (uintptr_t)a; 208e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uintptr_t b_chunk = (uintptr_t)b; 209e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 210e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(a != NULL); 211e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(b != NULL); 212e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 213e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return ((a_chunk > b_chunk) - (a_chunk < b_chunk)); 214e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 215e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 216e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Wrap red-black tree macros in functions. */ 217e476f8a161d445211fd6e54fe370275196e66bcbJason Evansrb_wrap(static JEMALLOC_ATTR(unused), arena_chunk_tree_dirty_, 218e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_tree_t, arena_chunk_t, link_dirty, arena_chunk_comp) 219e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 220e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int 221e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) 222e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 223e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uintptr_t a_mapelm = (uintptr_t)a; 224e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uintptr_t b_mapelm = (uintptr_t)b; 225e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 226e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(a != NULL); 227e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(b != NULL); 228e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 229e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm)); 230e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 231e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 232e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Wrap red-black tree macros in functions. */ 233e476f8a161d445211fd6e54fe370275196e66bcbJason Evansrb_wrap(static JEMALLOC_ATTR(unused), arena_run_tree_, arena_run_tree_t, 234e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t, link, arena_run_comp) 235e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 236e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int 237e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) 238e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 239e476f8a161d445211fd6e54fe370275196e66bcbJason Evans int ret; 240e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t a_size = a->bits & ~PAGE_MASK; 241e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t b_size = b->bits & ~PAGE_MASK; 242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 243e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (a_size > b_size) - (a_size < b_size); 244e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == 0) { 245e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uintptr_t a_mapelm, b_mapelm; 246e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 247e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY) 248e476f8a161d445211fd6e54fe370275196e66bcbJason Evans a_mapelm = (uintptr_t)a; 249e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else { 250e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 251e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Treat keys as though they are lower than anything 252e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * else. 253e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans a_mapelm = 0; 255e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 256e476f8a161d445211fd6e54fe370275196e66bcbJason Evans b_mapelm = (uintptr_t)b; 257e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 258e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm); 259e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 260e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 261e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 262e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 263e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 264e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Wrap red-black tree macros in functions. */ 265e476f8a161d445211fd6e54fe370275196e66bcbJason Evansrb_wrap(static JEMALLOC_ATTR(unused), arena_avail_tree_, arena_avail_tree_t, 266e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t, link, arena_avail_comp) 267e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 268e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void 269e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_rc_incr(arena_run_t *run, arena_bin_t *bin, const void *ptr) 270e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 271e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 272e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_t *arena; 273e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pagebeg, pageend, i; 274e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 275e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 276e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena = chunk->arena; 277e476f8a161d445211fd6e54fe370275196e66bcbJason Evans pagebeg = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; 278e476f8a161d445211fd6e54fe370275196e66bcbJason Evans pageend = ((uintptr_t)ptr + (uintptr_t)(bin->reg_size - 1) - 279e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (uintptr_t)chunk) >> PAGE_SHIFT; 280e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 281e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = pagebeg; i <= pageend; i++) { 282e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t mapbits = chunk->map[i].bits; 283e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 284e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (mapbits & CHUNK_MAP_DIRTY) { 285e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((mapbits & CHUNK_MAP_RC_MASK) == 0); 286e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty--; 287e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty--; 288e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits ^= CHUNK_MAP_DIRTY; 289e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 290e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((mapbits & CHUNK_MAP_RC_MASK) != CHUNK_MAP_RC_MASK); 291e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits += CHUNK_MAP_RC_ONE; 292e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[i].bits = mapbits; 293e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 294e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 295e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 296e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void 297e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_rc_decr(arena_run_t *run, arena_bin_t *bin, const void *ptr) 298e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 299e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 300e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_t *arena; 301e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pagebeg, pageend, mapbits, i; 302e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool dirtier = false; 303e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 304e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 305e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena = chunk->arena; 306e476f8a161d445211fd6e54fe370275196e66bcbJason Evans pagebeg = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; 307e476f8a161d445211fd6e54fe370275196e66bcbJason Evans pageend = ((uintptr_t)ptr + (uintptr_t)(bin->reg_size - 1) - 308e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (uintptr_t)chunk) >> PAGE_SHIFT; 309e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 310e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* First page. */ 311e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits = chunk->map[pagebeg].bits; 312e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits -= CHUNK_MAP_RC_ONE; 313e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((mapbits & CHUNK_MAP_RC_MASK) == 0) { 314e476f8a161d445211fd6e54fe370275196e66bcbJason Evans dirtier = true; 315e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((mapbits & CHUNK_MAP_DIRTY) == 0); 316e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits |= CHUNK_MAP_DIRTY; 317e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty++; 318e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty++; 319e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 320e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[pagebeg].bits = mapbits; 321e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 322e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (pageend - pagebeg >= 1) { 323e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 324e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Interior pages are completely consumed by the object being 325e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * deallocated, which means that the pages can be 326e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * unconditionally marked dirty. 327e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 328e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = pagebeg + 1; i < pageend; i++) { 329e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits = chunk->map[i].bits; 330e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits -= CHUNK_MAP_RC_ONE; 331e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((mapbits & CHUNK_MAP_RC_MASK) == 0); 332e476f8a161d445211fd6e54fe370275196e66bcbJason Evans dirtier = true; 333e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((mapbits & CHUNK_MAP_DIRTY) == 0); 334e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits |= CHUNK_MAP_DIRTY; 335e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty++; 336e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty++; 337e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[i].bits = mapbits; 338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Last page. */ 341e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits = chunk->map[pageend].bits; 342e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits -= CHUNK_MAP_RC_ONE; 343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((mapbits & CHUNK_MAP_RC_MASK) == 0) { 344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans dirtier = true; 345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((mapbits & CHUNK_MAP_DIRTY) == 0); 346e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits |= CHUNK_MAP_DIRTY; 347e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty++; 348e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty++; 349e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 350e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[pageend].bits = mapbits; 351e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 352e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 353e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (dirtier) { 354e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk->dirtied == false) { 355e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_tree_dirty_insert(&arena->chunks_dirty, 356e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk); 357e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->dirtied = true; 358e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 359e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 360e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Enforce opt_lg_dirty_mult. */ 361e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_lg_dirty_mult >= 0 && (arena->nactive >> 362e476f8a161d445211fd6e54fe370275196e66bcbJason Evans opt_lg_dirty_mult) < arena->ndirty) 363e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_purge(arena); 364e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 365e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 366e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 367e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void * 368e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_reg_alloc(arena_run_t *run, arena_bin_t *bin) 369e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 370e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 371e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned i, mask, bit, regind; 372e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 373e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run->magic == ARENA_RUN_MAGIC); 374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run->regs_minelm < bin->regs_mask_nelms); 375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 377e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Move the first check outside the loop, so that run->regs_minelm can 378e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * be updated unconditionally, without the possibility of updating it 379e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * multiple times. 380e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i = run->regs_minelm; 382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mask = run->regs_mask[i]; 383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (mask != 0) { 384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Usable allocation found. */ 385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bit = ffs((int)mask) - 1; 386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans regind = ((i << (LG_SIZEOF_INT + 3)) + bit); 388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(regind < bin->nregs); 389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (void *)(((uintptr_t)run) + bin->reg0_offset 390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans + (bin->reg_size * regind)); 391e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 392e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Clear bit. */ 393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mask ^= (1U << bit); 394e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_mask[i] = mask; 395e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 396e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_rc_incr(run, bin, ret); 397e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 398e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 399e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 400e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 401e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i++; i < bin->regs_mask_nelms; i++) { 402e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mask = run->regs_mask[i]; 403e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (mask != 0) { 404e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Usable allocation found. */ 405e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bit = ffs((int)mask) - 1; 406e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 407e476f8a161d445211fd6e54fe370275196e66bcbJason Evans regind = ((i << (LG_SIZEOF_INT + 3)) + bit); 408e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(regind < bin->nregs); 409e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (void *)(((uintptr_t)run) + bin->reg0_offset 410e476f8a161d445211fd6e54fe370275196e66bcbJason Evans + (bin->reg_size * regind)); 411e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 412e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Clear bit. */ 413e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mask ^= (1U << bit); 414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_mask[i] = mask; 415e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 416e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Make a note that nothing before this element 418e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * contains a free region. 419e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 420e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_minelm = i; /* Low payoff: + (mask == 0); */ 421e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 422e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_rc_incr(run, bin, ret); 423e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 424e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 425e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 426e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 427e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Not reached. */ 428e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(0); 429e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 430e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 431e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 432e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void 433e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_reg_dalloc(arena_run_t *run, arena_bin_t *bin, void *ptr, size_t size) 434e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 435e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned shift, diff, regind, elm, bit; 436e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 437e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run->magic == ARENA_RUN_MAGIC); 438e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 439e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 440e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Avoid doing division with a variable divisor if possible. Using 441e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * actual division here can reduce allocator throughput by over 20%! 442e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 443e476f8a161d445211fd6e54fe370275196e66bcbJason Evans diff = (unsigned)((uintptr_t)ptr - (uintptr_t)run - bin->reg0_offset); 444e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 445e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Rescale (factor powers of 2 out of the numerator and denominator). */ 446e476f8a161d445211fd6e54fe370275196e66bcbJason Evans shift = ffs(size) - 1; 447e476f8a161d445211fd6e54fe370275196e66bcbJason Evans diff >>= shift; 448e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size >>= shift; 449e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 450e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (size == 1) { 451e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* The divisor was a power of 2. */ 452e476f8a161d445211fd6e54fe370275196e66bcbJason Evans regind = diff; 453e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 454e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 455e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * To divide by a number D that is not a power of two we 456e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * multiply by (2^21 / D) and then right shift by 21 positions. 457e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 458e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * X / D 459e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 460e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * becomes 461e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 462e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * (X * size_invs[D - 3]) >> SIZE_INV_SHIFT 463e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 464e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * We can omit the first three elements, because we never 465e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * divide by 0, and 1 and 2 are both powers of two, which are 466e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * handled above. 467e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 468e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define SIZE_INV_SHIFT 21 469e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define SIZE_INV(s) (((1U << SIZE_INV_SHIFT) / (s)) + 1) 470e476f8a161d445211fd6e54fe370275196e66bcbJason Evans static const unsigned size_invs[] = { 471e476f8a161d445211fd6e54fe370275196e66bcbJason Evans SIZE_INV(3), 472e476f8a161d445211fd6e54fe370275196e66bcbJason Evans SIZE_INV(4), SIZE_INV(5), SIZE_INV(6), SIZE_INV(7), 473e476f8a161d445211fd6e54fe370275196e66bcbJason Evans SIZE_INV(8), SIZE_INV(9), SIZE_INV(10), SIZE_INV(11), 474e476f8a161d445211fd6e54fe370275196e66bcbJason Evans SIZE_INV(12), SIZE_INV(13), SIZE_INV(14), SIZE_INV(15), 475e476f8a161d445211fd6e54fe370275196e66bcbJason Evans SIZE_INV(16), SIZE_INV(17), SIZE_INV(18), SIZE_INV(19), 476e476f8a161d445211fd6e54fe370275196e66bcbJason Evans SIZE_INV(20), SIZE_INV(21), SIZE_INV(22), SIZE_INV(23), 477e476f8a161d445211fd6e54fe370275196e66bcbJason Evans SIZE_INV(24), SIZE_INV(25), SIZE_INV(26), SIZE_INV(27), 478e476f8a161d445211fd6e54fe370275196e66bcbJason Evans SIZE_INV(28), SIZE_INV(29), SIZE_INV(30), SIZE_INV(31) 479e476f8a161d445211fd6e54fe370275196e66bcbJason Evans }; 480e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 481e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (size <= ((sizeof(size_invs) / sizeof(unsigned)) + 2)) 482e476f8a161d445211fd6e54fe370275196e66bcbJason Evans regind = (diff * size_invs[size - 3]) >> SIZE_INV_SHIFT; 483e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else 484e476f8a161d445211fd6e54fe370275196e66bcbJason Evans regind = diff / size; 485e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef SIZE_INV 486e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef SIZE_INV_SHIFT 487e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 488e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(diff == regind * size); 489e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(regind < bin->nregs); 490e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 491e476f8a161d445211fd6e54fe370275196e66bcbJason Evans elm = regind >> (LG_SIZEOF_INT + 3); 492e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (elm < run->regs_minelm) 493e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_minelm = elm; 494e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bit = regind - (elm << (LG_SIZEOF_INT + 3)); 495e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((run->regs_mask[elm] & (1U << bit)) == 0); 496e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_mask[elm] |= (1U << bit); 497e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 498e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_rc_decr(run, bin, ptr); 499e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 500e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 501e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 502e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large, 503e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool zero) 504e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 505e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 506e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t old_ndirty, run_ind, total_pages, need_pages, rem_pages, i; 507e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 508e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 509e476f8a161d445211fd6e54fe370275196e66bcbJason Evans old_ndirty = chunk->ndirty; 510e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) 511e476f8a161d445211fd6e54fe370275196e66bcbJason Evans >> PAGE_SHIFT); 512e476f8a161d445211fd6e54fe370275196e66bcbJason Evans total_pages = (chunk->map[run_ind].bits & ~PAGE_MASK) >> 513e476f8a161d445211fd6e54fe370275196e66bcbJason Evans PAGE_SHIFT; 514e476f8a161d445211fd6e54fe370275196e66bcbJason Evans need_pages = (size >> PAGE_SHIFT); 515e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(need_pages > 0); 516e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(need_pages <= total_pages); 517e476f8a161d445211fd6e54fe370275196e66bcbJason Evans rem_pages = total_pages - need_pages; 518e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 519e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_avail_tree_remove(&arena->runs_avail, &chunk->map[run_ind]); 520e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->nactive += need_pages; 521e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 522e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Keep track of trailing unused pages for later use. */ 523e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (rem_pages > 0) { 524e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind+need_pages].bits = (rem_pages << 525e476f8a161d445211fd6e54fe370275196e66bcbJason Evans PAGE_SHIFT) | (chunk->map[run_ind+need_pages].bits & 526e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 527e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind+total_pages-1].bits = (rem_pages << 528e476f8a161d445211fd6e54fe370275196e66bcbJason Evans PAGE_SHIFT) | (chunk->map[run_ind+total_pages-1].bits & 529e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 530e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_avail_tree_insert(&arena->runs_avail, 531e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &chunk->map[run_ind+need_pages]); 532e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 533e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 534e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = 0; i < need_pages; i++) { 535e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Zero if necessary. */ 536e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (zero) { 537e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((chunk->map[run_ind + i].bits & CHUNK_MAP_ZEROED) 538e476f8a161d445211fd6e54fe370275196e66bcbJason Evans == 0) { 539e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)chunk + ((run_ind 540e476f8a161d445211fd6e54fe370275196e66bcbJason Evans + i) << PAGE_SHIFT)), 0, PAGE_SIZE); 541e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* CHUNK_MAP_ZEROED is cleared below. */ 542e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 543e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 544e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 545e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Update dirty page accounting. */ 546e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) { 547e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty--; 548e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty--; 549e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* CHUNK_MAP_DIRTY is cleared below. */ 550e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 551e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 552e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Initialize the chunk map. */ 553e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (large) { 554e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind + i].bits = CHUNK_MAP_LARGE 555e476f8a161d445211fd6e54fe370275196e66bcbJason Evans | CHUNK_MAP_ALLOCATED; 556e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 557e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind + i].bits = (i << CHUNK_MAP_PG_SHIFT) 558e476f8a161d445211fd6e54fe370275196e66bcbJason Evans | CHUNK_MAP_ALLOCATED; 559e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 560e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 561e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 562e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (large) { 563e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 564e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Set the run size only in the first element for large runs. 565e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * This is primarily a debugging aid, since the lack of size 566e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * info for trailing pages only matters if the application 567e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * tries to operate on an interior pointer. 568e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 569e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind].bits |= size; 570e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 571e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 572e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Initialize the first page's refcount to 1, so that the run 573e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * header is protected from dirty page purging. 574e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 575e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind].bits += CHUNK_MAP_RC_ONE; 576e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 577e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 578e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 579e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_chunk_t * 580e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_alloc(arena_t *arena) 581e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 582e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 583e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t i; 584e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 585e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->spare != NULL) { 586e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = arena->spare; 587e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->spare = NULL; 588e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 58941631d00618d7262125e501c91d31b4d70e605faJason Evans bool zero; 59041631d00618d7262125e501c91d31b4d70e605faJason Evans size_t zeroed; 59141631d00618d7262125e501c91d31b4d70e605faJason Evans 59241631d00618d7262125e501c91d31b4d70e605faJason Evans zero = false; 59341631d00618d7262125e501c91d31b4d70e605faJason Evans chunk = (arena_chunk_t *)chunk_alloc(chunksize, &zero); 594e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk == NULL) 595e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 596e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 597e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.mapped += chunksize; 598e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 599e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 600e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->arena = arena; 601e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->dirtied = false; 602e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 603e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 604e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Claim that no pages are in use, since the header is merely 605e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * overhead. 606e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 607e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty = 0; 608e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 609e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 610e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Initialize the map to contain one maximal free untouched run. 61141631d00618d7262125e501c91d31b4d70e605faJason Evans * Mark the pages as zeroed iff chunk_alloc() returned a zeroed 61241631d00618d7262125e501c91d31b4d70e605faJason Evans * chunk. 613e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 61441631d00618d7262125e501c91d31b4d70e605faJason Evans zeroed = zero ? CHUNK_MAP_ZEROED : 0; 615e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = 0; i < arena_chunk_header_npages; i++) 616e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[i].bits = 0; 61741631d00618d7262125e501c91d31b4d70e605faJason Evans chunk->map[i].bits = arena_maxclass | zeroed; 61841631d00618d7262125e501c91d31b4d70e605faJason Evans for (i++; i < chunk_npages-1; i++) 61941631d00618d7262125e501c91d31b4d70e605faJason Evans chunk->map[i].bits = zeroed; 62041631d00618d7262125e501c91d31b4d70e605faJason Evans chunk->map[chunk_npages-1].bits = arena_maxclass | zeroed; 621e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 622e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 623e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Insert the run into the runs_avail tree. */ 624e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_avail_tree_insert(&arena->runs_avail, 625e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &chunk->map[arena_chunk_header_npages]); 626e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 627e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (chunk); 628e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 629e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 630e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 631e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) 632e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 633e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 634e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->spare != NULL) { 635e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->spare->dirtied) { 636e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_tree_dirty_remove( 637e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &chunk->arena->chunks_dirty, arena->spare); 638e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty -= arena->spare->ndirty; 639e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 640e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk_dealloc((void *)arena->spare, chunksize); 641e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 642e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.mapped -= chunksize; 643e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 644e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 645e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 646e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 647e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Remove run from runs_avail, regardless of whether this chunk 648e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * will be cached, so that the arena does not use it. Dirty page 649e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * flushing only uses the chunks_dirty tree, so leaving this chunk in 650e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * the chunks_* trees is sufficient for that purpose. 651e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 652e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_avail_tree_remove(&arena->runs_avail, 653e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &chunk->map[arena_chunk_header_npages]); 654e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 655e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->spare = chunk; 656e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 657e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 658e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t * 659e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_alloc(arena_t *arena, size_t size, bool large, bool zero) 660e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 661e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 662e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 663e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t *mapelm, key; 664e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 665e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size <= arena_maxclass); 666e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((size & PAGE_MASK) == 0); 667e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 668e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Search the arena's chunks for the lowest best fit. */ 669e476f8a161d445211fd6e54fe370275196e66bcbJason Evans key.bits = size | CHUNK_MAP_KEY; 670e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapelm = arena_avail_tree_nsearch(&arena->runs_avail, &key); 671e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (mapelm != NULL) { 672e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); 673e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind = ((uintptr_t)mapelm - (uintptr_t)run_chunk->map) 674e476f8a161d445211fd6e54fe370275196e66bcbJason Evans / sizeof(arena_chunk_map_t); 675e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 676e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run = (arena_run_t *)((uintptr_t)run_chunk + (pageind 677e476f8a161d445211fd6e54fe370275196e66bcbJason Evans << PAGE_SHIFT)); 678e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_split(arena, run, size, large, zero); 679e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (run); 680e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 681e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 682e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 683e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * No usable runs. Create a new chunk from which to allocate the run. 684e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 685e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = arena_chunk_alloc(arena); 686e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk == NULL) 687e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 688e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run = (arena_run_t *)((uintptr_t)chunk + (arena_chunk_header_npages << 689e476f8a161d445211fd6e54fe370275196e66bcbJason Evans PAGE_SHIFT)); 690e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Update page map. */ 691e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_split(arena, run, size, large, zero); 692e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (run); 693e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 694e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 695e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 696e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_purge(arena_t *arena) 697e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 698e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 699e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t i, npages; 700e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG 701e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t ndirty = 0; 702e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 703e476f8a161d445211fd6e54fe370275196e66bcbJason Evans rb_foreach_begin(arena_chunk_t, link_dirty, &arena->chunks_dirty, 704e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk) { 705e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(chunk->dirtied); 706e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ndirty += chunk->ndirty; 707e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } rb_foreach_end(arena_chunk_t, link_dirty, &arena->chunks_dirty, chunk) 708e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(ndirty == arena->ndirty); 709e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 710e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((arena->nactive >> opt_lg_dirty_mult) < arena->ndirty); 711e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 712e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 713e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.npurge++; 714e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 715e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 716e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 717e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Iterate downward through chunks until enough dirty memory has been 718e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * purged. Terminate as soon as possible in order to minimize the 719e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * number of system calls, even if a chunk has only been partially 720e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * purged. 721e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 722e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 723e476f8a161d445211fd6e54fe370275196e66bcbJason Evans while ((arena->nactive >> (opt_lg_dirty_mult + 1)) < arena->ndirty) { 724e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = arena_chunk_tree_dirty_last(&arena->chunks_dirty); 725e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(chunk != NULL); 726e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 727e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = chunk_npages - 1; chunk->ndirty > 0; i--) { 728e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(i >= arena_chunk_header_npages); 729e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk->map[i].bits & CHUNK_MAP_DIRTY) { 730e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[i].bits ^= CHUNK_MAP_DIRTY; 731e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Find adjacent dirty run(s). */ 732e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (npages = 1; i > arena_chunk_header_npages 733e476f8a161d445211fd6e54fe370275196e66bcbJason Evans && (chunk->map[i - 1].bits & 734e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_DIRTY); npages++) { 735e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i--; 736e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[i].bits ^= CHUNK_MAP_DIRTY; 737e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 738e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty -= npages; 739e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty -= npages; 740e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 741e476f8a161d445211fd6e54fe370275196e66bcbJason Evans madvise((void *)((uintptr_t)chunk + (i << 742e476f8a161d445211fd6e54fe370275196e66bcbJason Evans PAGE_SHIFT)), (npages << PAGE_SHIFT), 743e476f8a161d445211fd6e54fe370275196e66bcbJason Evans MADV_DONTNEED); 744e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 745e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmadvise++; 746e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.purged += npages; 747e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 748e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((arena->nactive >> (opt_lg_dirty_mult + 1)) 749e476f8a161d445211fd6e54fe370275196e66bcbJason Evans >= arena->ndirty) 750e476f8a161d445211fd6e54fe370275196e66bcbJason Evans break; 751e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 752e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 753e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 754e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk->ndirty == 0) { 755e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_tree_dirty_remove(&arena->chunks_dirty, 756e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk); 757e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->dirtied = false; 758e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 759e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 760e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 761e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 762e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 763e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) 764e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 765e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 766e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t size, run_ind, run_pages; 767e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 768e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 769e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) 770e476f8a161d445211fd6e54fe370275196e66bcbJason Evans >> PAGE_SHIFT); 771e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run_ind >= arena_chunk_header_npages); 772e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run_ind < chunk_npages); 773e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((chunk->map[run_ind].bits & CHUNK_MAP_LARGE) != 0) 774e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = chunk->map[run_ind].bits & ~PAGE_MASK; 775e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else 776e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = run->bin->run_size; 777e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run_pages = (size >> PAGE_SHIFT); 778e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->nactive -= run_pages; 779e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 780e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Mark pages as unallocated in the chunk map. */ 781e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (dirty) { 782e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t i; 783e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 784e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = 0; i < run_pages; i++) { 785e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 786e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * When (dirty == true), *all* pages within the run 787e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * need to have their dirty bits set, because only 788e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * small runs can create a mixture of clean/dirty 789e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * pages, but such runs are passed to this function 790e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * with (dirty == false). 791e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 792e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((chunk->map[run_ind + i].bits & CHUNK_MAP_DIRTY) 793e476f8a161d445211fd6e54fe370275196e66bcbJason Evans == 0); 794e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty++; 795e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty++; 796e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind + i].bits = CHUNK_MAP_DIRTY; 797e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 798e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 799e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t i; 800e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 801e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = 0; i < run_pages; i++) { 802e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind + i].bits &= ~(CHUNK_MAP_LARGE | 803e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_ALLOCATED); 804e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 805e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 806e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & 807e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 808e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind+run_pages-1].bits = size | 809e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (chunk->map[run_ind+run_pages-1].bits & CHUNK_MAP_FLAGS_MASK); 810e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 811e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Try to coalesce forward. */ 812e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (run_ind + run_pages < chunk_npages && 813e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (chunk->map[run_ind+run_pages].bits & CHUNK_MAP_ALLOCATED) == 0) { 814e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t nrun_size = chunk->map[run_ind+run_pages].bits & 815e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ~PAGE_MASK; 816e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 817e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 818e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Remove successor from runs_avail; the coalesced run is 819e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * inserted later. 820e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 821e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_avail_tree_remove(&arena->runs_avail, 822e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &chunk->map[run_ind+run_pages]); 823e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 824e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size += nrun_size; 825e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run_pages = size >> PAGE_SHIFT; 826e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 827e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((chunk->map[run_ind+run_pages-1].bits & ~PAGE_MASK) 828e476f8a161d445211fd6e54fe370275196e66bcbJason Evans == nrun_size); 829e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & 830e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 831e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind+run_pages-1].bits = size | 832e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (chunk->map[run_ind+run_pages-1].bits & 833e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 834e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 835e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 836e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Try to coalesce backward. */ 837e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (run_ind > arena_chunk_header_npages && (chunk->map[run_ind-1].bits & 838e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_ALLOCATED) == 0) { 839e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t prun_size = chunk->map[run_ind-1].bits & ~PAGE_MASK; 840e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 841e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run_ind -= prun_size >> PAGE_SHIFT; 842e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 843e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 844e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Remove predecessor from runs_avail; the coalesced run is 845e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * inserted later. 846e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 847e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_avail_tree_remove(&arena->runs_avail, 848e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &chunk->map[run_ind]); 849e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 850e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size += prun_size; 851e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run_pages = size >> PAGE_SHIFT; 852e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 853e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((chunk->map[run_ind].bits & ~PAGE_MASK) == prun_size); 854e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind].bits = size | (chunk->map[run_ind].bits & 855e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 856e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind+run_pages-1].bits = size | 857e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (chunk->map[run_ind+run_pages-1].bits & 858e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 859e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 860e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 861e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Insert into runs_avail, now that coalescing is complete. */ 862e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_avail_tree_insert(&arena->runs_avail, &chunk->map[run_ind]); 863e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 864e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Deallocate chunk if it is now completely unused. */ 865e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((chunk->map[arena_chunk_header_npages].bits & (~PAGE_MASK | 866e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_ALLOCATED)) == arena_maxclass) 867e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_dealloc(arena, chunk); 868e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 869e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (dirty) { 870e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk->dirtied == false) { 871e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_tree_dirty_insert(&arena->chunks_dirty, 872e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk); 873e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->dirtied = true; 874e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 875e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 876e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Enforce opt_lg_dirty_mult. */ 877e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_lg_dirty_mult >= 0 && (arena->nactive >> 878e476f8a161d445211fd6e54fe370275196e66bcbJason Evans opt_lg_dirty_mult) < arena->ndirty) 879e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_purge(arena); 880e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 881e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 882e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 883e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 884e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 885e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t oldsize, size_t newsize) 886e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 887e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT; 888e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t head_npages = (oldsize - newsize) >> PAGE_SHIFT; 889e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 890e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(oldsize > newsize); 891e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 892e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 893e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Update the chunk map so that arena_run_dalloc() can treat the 894e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * leading run as separately allocated. 895e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 896e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((chunk->map[pageind].bits & CHUNK_MAP_DIRTY) == 0); 897e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[pageind].bits = (oldsize - newsize) | CHUNK_MAP_LARGE | 898e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_ALLOCATED; 899e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((chunk->map[pageind+head_npages].bits & CHUNK_MAP_DIRTY) == 0); 900e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[pageind+head_npages].bits = newsize | CHUNK_MAP_LARGE | 901e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_ALLOCATED; 902e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 903e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_dalloc(arena, run, false); 904e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 905e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 906e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 907e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 908e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t oldsize, size_t newsize, bool dirty) 909e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 910e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT; 911e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t npages = newsize >> PAGE_SHIFT; 912e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 913e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(oldsize > newsize); 914e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 915e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 916e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Update the chunk map so that arena_run_dalloc() can treat the 917e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * trailing run as separately allocated. 918e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 919e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((chunk->map[pageind].bits & CHUNK_MAP_DIRTY) == 0); 920e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[pageind].bits = newsize | CHUNK_MAP_LARGE | 921e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_ALLOCATED; 922e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((chunk->map[pageind+npages].bits & CHUNK_MAP_DIRTY) == 0); 923e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[pageind+npages].bits = (oldsize - newsize) | CHUNK_MAP_LARGE 924e476f8a161d445211fd6e54fe370275196e66bcbJason Evans | CHUNK_MAP_ALLOCATED; 925e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 926e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize), 927e476f8a161d445211fd6e54fe370275196e66bcbJason Evans dirty); 928e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 929e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 930e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t * 931e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) 932e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 933e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t *mapelm; 934e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 935e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned i, remainder; 936e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 937e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Look for a usable run. */ 938e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapelm = arena_run_tree_first(&bin->runs); 939e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (mapelm != NULL) { 940e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 941e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind; 942e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 943e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* run is guaranteed to have available space. */ 944e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_remove(&bin->runs, mapelm); 945e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 946e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm); 947e476f8a161d445211fd6e54fe370275196e66bcbJason Evans pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / 948e476f8a161d445211fd6e54fe370275196e66bcbJason Evans sizeof(arena_chunk_map_t)); 949e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - 950e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT)) 951e476f8a161d445211fd6e54fe370275196e66bcbJason Evans << PAGE_SHIFT)); 952e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 953e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.reruns++; 954e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 955e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (run); 956e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 957e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* No existing runs have any space available. */ 958e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 959e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Allocate a new run. */ 960e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run = arena_run_alloc(arena, bin->run_size, false, false); 961e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (run == NULL) 962e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 963e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 964e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Initialize run internals. */ 965e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->bin = bin; 966e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 967e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = 0; i < bin->regs_mask_nelms - 1; i++) 968e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_mask[i] = UINT_MAX; 969e476f8a161d445211fd6e54fe370275196e66bcbJason Evans remainder = bin->nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1); 970e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (remainder == 0) 971e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_mask[i] = UINT_MAX; 972e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else { 973e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* The last element has spare bits that need to be unset. */ 974e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_mask[i] = (UINT_MAX >> ((1U << (LG_SIZEOF_INT + 3)) 975e476f8a161d445211fd6e54fe370275196e66bcbJason Evans - remainder)); 976e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 977e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 978e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->regs_minelm = 0; 979e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 980e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->nfree = bin->nregs; 981e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG 982e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->magic = ARENA_RUN_MAGIC; 983e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 984e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 985e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 986e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.nruns++; 987e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.curruns++; 988e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (bin->stats.curruns > bin->stats.highruns) 989e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.highruns = bin->stats.curruns; 990e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 991e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (run); 992e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 993e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 994e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* bin->runcur must have space available before this function is called. */ 995e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void * 996e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_malloc_easy(arena_t *arena, arena_bin_t *bin, arena_run_t *run) 997e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 998e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 999e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1000e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run->magic == ARENA_RUN_MAGIC); 1001e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run->nfree > 0); 1002e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1003e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = arena_run_reg_alloc(run, bin); 1004e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(ret != NULL); 1005e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->nfree--; 1006e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1007e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1008e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1009e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1010e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Re-fill bin->runcur, then call arena_bin_malloc_easy(). */ 1011e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void * 1012e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin) 1013e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1014e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1015e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = arena_bin_nonfull_run_get(arena, bin); 1016e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (bin->runcur == NULL) 1017e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1018e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(bin->runcur->magic == ARENA_RUN_MAGIC); 1019e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(bin->runcur->nfree > 0); 1020e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1021e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (arena_bin_malloc_easy(arena, bin, bin->runcur)); 1022e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1023e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1024e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE 1025e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid 1026e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_tcache_fill(arena_t *arena, tcache_bin_t *tbin, size_t binind) 1027e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1028e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned i, nfill; 1029e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin; 1030e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 1031e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ptr; 1032e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1033e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(tbin->ncached == 0); 1034e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1035e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[binind]; 1036e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1037e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (i = 0, nfill = (tcache_nslots >> 1); i < nfill; i++) { 1038e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((run = bin->runcur) != NULL && run->nfree > 0) 1039e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ptr = arena_bin_malloc_easy(arena, bin, run); 1040e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else 1041e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ptr = arena_bin_malloc_hard(arena, bin); 1042e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ptr == NULL) { 1043e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (i > 0) { 1044e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1045e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Move valid pointers to the base of 1046e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * tbin->slots. 1047e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1048e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memmove(&tbin->slots[0], 1049e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &tbin->slots[nfill - i], 1050e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i * sizeof(void *)); 1051e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1052e476f8a161d445211fd6e54fe370275196e66bcbJason Evans break; 1053e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1054e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1055e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Fill slots such that the objects lowest in memory come last. 1056e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * This causes tcache to use low objects first. 1057e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1058e476f8a161d445211fd6e54fe370275196e66bcbJason Evans tbin->slots[nfill - 1 - i] = ptr; 1059e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1060e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1061e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.nfills++; 1062e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.nrequests += tbin->tstats.nrequests; 1063e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (bin->reg_size <= small_maxclass) { 1064e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmalloc_small += (i - tbin->ncached); 1065e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_small += (i - tbin->ncached) * 1066e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size; 1067e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmalloc_small += tbin->tstats.nrequests; 1068e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1069e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmalloc_medium += (i - tbin->ncached); 1070e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_medium += (i - tbin->ncached) * 1071e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size; 1072e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmalloc_medium += tbin->tstats.nrequests; 1073e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1074e476f8a161d445211fd6e54fe370275196e66bcbJason Evans tbin->tstats.nrequests = 0; 1075e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1076e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1077e476f8a161d445211fd6e54fe370275196e66bcbJason Evans tbin->ncached = i; 1078e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (tbin->ncached > tbin->high_water) 1079e476f8a161d445211fd6e54fe370275196e66bcbJason Evans tbin->high_water = tbin->ncached; 1080e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1081e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1082e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1083e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 1084e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Calculate bin->run_size such that it meets the following constraints: 1085e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 1086e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * *) bin->run_size >= min_run_size 1087e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * *) bin->run_size <= arena_maxclass 1088e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * *) bin->run_size <= RUN_MAX_SMALL 1089e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed). 1090e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * *) run header size < PAGE_SIZE 1091e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 1092e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * bin->nregs, bin->regs_mask_nelms, and bin->reg0_offset are 1093e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * also calculated here, since these settings are all interdependent. 1094e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1095e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic size_t 1096e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_run_size_calc(arena_bin_t *bin, size_t min_run_size) 1097e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1098e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t try_run_size, good_run_size; 1099e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned good_nregs, good_mask_nelms, good_reg0_offset; 1100e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned try_nregs, try_mask_nelms, try_reg0_offset; 1101e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1102e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(min_run_size >= PAGE_SIZE); 1103e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(min_run_size <= arena_maxclass); 1104e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(min_run_size <= RUN_MAX_SMALL); 1105e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1106e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1107e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Calculate known-valid settings before entering the run_size 1108e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * expansion loop, so that the first part of the loop always copies 1109e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * valid settings. 1110e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 1111e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * The do..while loop iteratively reduces the number of regions until 1112e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * the run header and the regions no longer overlap. A closed formula 1113e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * would be quite messy, since there is an interdependency between the 1114e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * header's mask length and the number of regions. 1115e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1116e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_run_size = min_run_size; 1117e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_nregs = ((try_run_size - sizeof(arena_run_t)) / bin->reg_size) 1118e476f8a161d445211fd6e54fe370275196e66bcbJason Evans + 1; /* Counter-act try_nregs-- in loop. */ 1119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans do { 1120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_nregs--; 1121e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_mask_nelms = (try_nregs >> (LG_SIZEOF_INT + 3)) + 1122e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ((try_nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1)) ? 1 : 0); 1123e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_reg0_offset = try_run_size - (try_nregs * bin->reg_size); 1124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } while (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1)) 1125e476f8a161d445211fd6e54fe370275196e66bcbJason Evans > try_reg0_offset); 1126e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1127e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* run_size expansion loop. */ 1128e476f8a161d445211fd6e54fe370275196e66bcbJason Evans do { 1129e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1130e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Copy valid settings before trying more aggressive settings. 1131e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1132e476f8a161d445211fd6e54fe370275196e66bcbJason Evans good_run_size = try_run_size; 1133e476f8a161d445211fd6e54fe370275196e66bcbJason Evans good_nregs = try_nregs; 1134e476f8a161d445211fd6e54fe370275196e66bcbJason Evans good_mask_nelms = try_mask_nelms; 1135e476f8a161d445211fd6e54fe370275196e66bcbJason Evans good_reg0_offset = try_reg0_offset; 1136e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1137e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Try more aggressive settings. */ 1138e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_run_size += PAGE_SIZE; 1139e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_nregs = ((try_run_size - sizeof(arena_run_t)) / 1140e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size) + 1; /* Counter-act try_nregs-- in loop. */ 1141e476f8a161d445211fd6e54fe370275196e66bcbJason Evans do { 1142e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_nregs--; 1143e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_mask_nelms = (try_nregs >> (LG_SIZEOF_INT + 3)) + 1144e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ((try_nregs & ((1U << (LG_SIZEOF_INT + 3)) - 1)) ? 1145e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1 : 0); 1146e476f8a161d445211fd6e54fe370275196e66bcbJason Evans try_reg0_offset = try_run_size - (try_nregs * 1147e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size); 1148e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } while (sizeof(arena_run_t) + (sizeof(unsigned) * 1149e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (try_mask_nelms - 1)) > try_reg0_offset); 1150e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } while (try_run_size <= arena_maxclass && try_run_size <= RUN_MAX_SMALL 1151e476f8a161d445211fd6e54fe370275196e66bcbJason Evans && RUN_MAX_OVRHD * (bin->reg_size << 3) > RUN_MAX_OVRHD_RELAX 1152e476f8a161d445211fd6e54fe370275196e66bcbJason Evans && (try_reg0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size 1153e476f8a161d445211fd6e54fe370275196e66bcbJason Evans && (sizeof(arena_run_t) + (sizeof(unsigned) * (try_mask_nelms - 1))) 1154e476f8a161d445211fd6e54fe370275196e66bcbJason Evans < PAGE_SIZE); 1155e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1156e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(sizeof(arena_run_t) + (sizeof(unsigned) * (good_mask_nelms - 1)) 1157e476f8a161d445211fd6e54fe370275196e66bcbJason Evans <= good_reg0_offset); 1158e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((good_mask_nelms << (LG_SIZEOF_INT + 3)) >= good_nregs); 1159e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1160e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Copy final settings. */ 1161e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->run_size = good_run_size; 1162e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->nregs = good_nregs; 1163e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->regs_mask_nelms = good_mask_nelms; 1164e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg0_offset = good_reg0_offset; 1165e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1166e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (good_run_size); 1167e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1168e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1169e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 1170e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_small(arena_t *arena, size_t size, bool zero) 1171e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1172e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 1173e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin; 1174e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 1175e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t binind; 1176e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1177e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = small_size2bin[size]; 1178e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(binind < mbin0); 1179e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[binind]; 1180e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = bin->reg_size; 1181e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1182e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1183e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((run = bin->runcur) != NULL && run->nfree > 0) 1184e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = arena_bin_malloc_easy(arena, bin, run); 1185e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else 1186e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = arena_bin_malloc_hard(arena, bin); 1187e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1188e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == NULL) { 1189e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1190e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1191e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1192e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1193e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1194e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# ifdef JEMALLOC_TCACHE 1195e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (isthreaded == false) { 1196e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# endif 1197e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.nrequests++; 1198e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmalloc_small++; 1199e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# ifdef JEMALLOC_TCACHE 1200e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1201e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# endif 1202e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_small += size; 1203e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1204e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1205e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1206e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (zero == false) { 1207e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1208e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk) 1209e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0xa5, size); 1210e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else if (opt_zero) 1211e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0, size); 1212e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1213e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else 1214e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0, size); 1215e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1216e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1217e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1218e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1219e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 1220e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_medium(arena_t *arena, size_t size, bool zero) 1221e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1222e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 1223e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin; 1224e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 1225e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t binind; 1226e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1227e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = MEDIUM_CEILING(size); 1228e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = mbin0 + ((size - medium_min) >> lg_mspace); 1229e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(binind < nbins); 1230e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[binind]; 1231e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(bin->reg_size == size); 1232e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1233e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1234e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((run = bin->runcur) != NULL && run->nfree > 0) 1235e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = arena_bin_malloc_easy(arena, bin, run); 1236e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else 1237e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = arena_bin_malloc_hard(arena, bin); 1238e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1239e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == NULL) { 1240e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1241e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1243e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1244e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1245e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# ifdef JEMALLOC_TCACHE 1246e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (isthreaded == false) { 1247e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# endif 1248e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.nrequests++; 1249e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmalloc_medium++; 1250e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# ifdef JEMALLOC_TCACHE 1251e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1252e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# endif 1253e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_medium += size; 1254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1255e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1256e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1257e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (zero == false) { 1258e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1259e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk) 1260e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0xa5, size); 1261e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else if (opt_zero) 1262e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0, size); 1263e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1264e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else 1265e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0, size); 1266e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1267e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1268e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1269e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1270e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void * 1271e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_large(arena_t *arena, size_t size, bool zero) 1272e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1273e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 1274e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1275e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Large allocation. */ 1276e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = PAGE_CEILING(size); 1277e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1278e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (void *)arena_run_alloc(arena, size, true, zero); 1279e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == NULL) { 1280e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1281e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1282e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1283e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1284e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmalloc_large++; 1285e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_large += size; 1286e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; 1287e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; 1288e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > 1289e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { 1290e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = 1291e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; 1292e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1293e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1294e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1295e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1296e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (zero == false) { 1297e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1298e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk) 1299e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0xa5, size); 1300e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else if (opt_zero) 1301e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0, size); 1302e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1303e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1304e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1305e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1306e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1307e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1308e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 1309e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc(size_t size, bool zero) 1310e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1311e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1312e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size != 0); 1313e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(QUANTUM_CEILING(size) <= arena_maxclass); 1314e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1315e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (size <= bin_maxclass) { 1316e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE 1317e476f8a161d445211fd6e54fe370275196e66bcbJason Evans tcache_t *tcache; 1318e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1319e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((tcache = tcache_get()) != NULL) 1320e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (tcache_alloc(tcache, size, zero)); 1321e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1322e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (size <= small_maxclass) 1323e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (arena_malloc_small(choose_arena(), size, zero)); 1324e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else { 1325e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (arena_malloc_medium(choose_arena(), size, 1326e476f8a161d445211fd6e54fe370275196e66bcbJason Evans zero)); 1327e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1328e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else 1329e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (arena_malloc_large(choose_arena(), size, zero)); 1330e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1331e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1332e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Only handles large allocations that require more than page alignment. */ 1333e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 1334e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_palloc(arena_t *arena, size_t alignment, size_t size, size_t alloc_size) 1335e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1336e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 1337e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t offset; 1338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 1339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((size & PAGE_MASK) == 0); 1341e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((alignment & PAGE_MASK) == 0); 1342e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (void *)arena_run_alloc(arena, alloc_size, true, false); 1345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == NULL) { 1346e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1347e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1348e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1349e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1350e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ret); 1351e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1352e476f8a161d445211fd6e54fe370275196e66bcbJason Evans offset = (uintptr_t)ret & (alignment - 1); 1353e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((offset & PAGE_MASK) == 0); 1354e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(offset < alloc_size); 1355e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (offset == 0) 1356e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_trim_tail(arena, chunk, ret, alloc_size, size, false); 1357e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else { 1358e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t leadsize, trailsize; 1359e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1360e476f8a161d445211fd6e54fe370275196e66bcbJason Evans leadsize = alignment - offset; 1361e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (leadsize > 0) { 1362e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_trim_head(arena, chunk, ret, alloc_size, 1363e476f8a161d445211fd6e54fe370275196e66bcbJason Evans alloc_size - leadsize); 1364e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (void *)((uintptr_t)ret + leadsize); 1365e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1366e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1367e476f8a161d445211fd6e54fe370275196e66bcbJason Evans trailsize = alloc_size - leadsize - size; 1368e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (trailsize != 0) { 1369e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Trim trailing space. */ 1370e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(trailsize < alloc_size); 1371e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_trim_tail(arena, chunk, ret, size + trailsize, 1372e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size, false); 1373e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1377e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.nmalloc_large++; 1378e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_large += size; 1379e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].nrequests++; 1380e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns++; 1381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns > 1382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns) { 1383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].highruns = 1384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns; 1385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk) 1391e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0xa5, size); 1392e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else if (opt_zero) 1393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0, size); 1394e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1395e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1396e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1397e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1398e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool 1399e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_is_large(const void *ptr) 1400e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1401e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 1402e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind, mapbits; 1403e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1404e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(ptr != NULL); 1405e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(CHUNK_ADDR2BASE(ptr) != ptr); 1406e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1407e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 1408e476f8a161d445211fd6e54fe370275196e66bcbJason Evans pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT); 1409e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits = chunk->map[pageind].bits; 1410e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); 1411e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return ((mapbits & CHUNK_MAP_LARGE) != 0); 1412e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1413e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Return the size of the allocation pointed to by ptr. */ 1415e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssize_t 1416e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_salloc(const void *ptr) 1417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1418e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t ret; 1419e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 1420e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind, mapbits; 1421e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1422e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(ptr != NULL); 1423e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(CHUNK_ADDR2BASE(ptr) != ptr); 1424e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1425e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 1426e476f8a161d445211fd6e54fe370275196e66bcbJason Evans pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT); 1427e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mapbits = chunk->map[pageind].bits; 1428e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((mapbits & CHUNK_MAP_ALLOCATED) != 0); 1429e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((mapbits & CHUNK_MAP_LARGE) == 0) { 1430e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + 1431e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (uintptr_t)((pageind - ((mapbits & CHUNK_MAP_PG_MASK) >> 1432e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_PG_SHIFT)) << PAGE_SHIFT)); 1433e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run->magic == ARENA_RUN_MAGIC); 1434e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = run->bin->reg_size; 1435e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1436e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = mapbits & ~PAGE_MASK; 1437e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(ret != 0); 1438e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1439e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1440e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1441e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1442e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1443e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 1444e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 1445e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin) 1446e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1447e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t run_ind; 1448e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1449e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Deallocate run. */ 1450e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (run == bin->runcur) 1451e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = NULL; 1452e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else if (bin->nregs != 1) { 1453e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t run_pageind = (((uintptr_t)run - 1454e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (uintptr_t)chunk)) >> PAGE_SHIFT; 1455e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t *run_mapelm = 1456e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &chunk->map[run_pageind]; 1457e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1458e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * This block's conditional is necessary because if the 1459e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * run only contains one region, then it never gets 1460e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * inserted into the non-full runs tree. 1461e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1462e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_remove(&bin->runs, run_mapelm); 1463e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1464e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1465e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Mark the first page as dirty. The dirty bit for every other page in 1466e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * the run is already properly set, which means we can call 1467e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * arena_run_dalloc(..., false), thus potentially avoiding the needless 1468e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * creation of many dirty pages. 1469e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1470e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> PAGE_SHIFT); 1471e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((chunk->map[run_ind].bits & CHUNK_MAP_DIRTY) == 0); 1472e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[run_ind].bits |= CHUNK_MAP_DIRTY; 1473e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty++; 1474e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty++; 1475e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1476e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG 1477e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->magic = 0; 1478e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1479e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_dalloc(arena, run, false); 1480e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1481e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->stats.curruns--; 1482e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1483e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1484e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk->dirtied == false) { 1485e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_tree_dirty_insert(&arena->chunks_dirty, chunk); 1486e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->dirtied = true; 1487e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1488e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Enforce opt_lg_dirty_mult. */ 1489e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_lg_dirty_mult >= 0 && (arena->nactive >> opt_lg_dirty_mult) < 1490e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty) 1491e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_purge(arena); 1492e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1493e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1494e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid 1495e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr, 1496e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t *mapelm) 1497e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1498e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind; 1499e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 1500e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin; 1501e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t size; 1502e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1503e476f8a161d445211fd6e54fe370275196e66bcbJason Evans pageind = (((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT); 1504e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - 1505e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ((mapelm->bits & CHUNK_MAP_PG_MASK) >> CHUNK_MAP_PG_SHIFT)) << 1506e476f8a161d445211fd6e54fe370275196e66bcbJason Evans PAGE_SHIFT)); 1507e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run->magic == ARENA_RUN_MAGIC); 1508e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = run->bin; 1509e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = bin->reg_size; 1510e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1511e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1512e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk) 1513e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ptr, 0x5a, size); 1514e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1515e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1516e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_reg_dalloc(run, bin, ptr, size); 1517e476f8a161d445211fd6e54fe370275196e66bcbJason Evans run->nfree++; 1518e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1519e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (run->nfree == bin->nregs) 1520e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_dalloc_bin_run(arena, chunk, run, bin); 1521e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else if (run->nfree == 1 && run != bin->runcur) { 1522e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1523e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Make sure that bin->runcur always refers to the lowest 1524e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * non-full run, if one exists. 1525e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1526e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (bin->runcur == NULL) 1527e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = run; 1528e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else if ((uintptr_t)run < (uintptr_t)bin->runcur) { 1529e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Switch runcur. */ 1530e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (bin->runcur->nfree > 0) { 1531e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *runcur_chunk = 1532e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_ADDR2BASE(bin->runcur); 1533e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t runcur_pageind = 1534e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (((uintptr_t)bin->runcur - 1535e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (uintptr_t)runcur_chunk)) >> PAGE_SHIFT; 1536e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t *runcur_mapelm = 1537e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &runcur_chunk->map[runcur_pageind]; 1538e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1539e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Insert runcur. */ 1540e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_insert(&bin->runs, 1541e476f8a161d445211fd6e54fe370275196e66bcbJason Evans runcur_mapelm); 1542e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1543e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = run; 1544e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1545e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t run_pageind = (((uintptr_t)run - 1546e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (uintptr_t)chunk)) >> PAGE_SHIFT; 1547e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t *run_mapelm = 1548e476f8a161d445211fd6e54fe370275196e66bcbJason Evans &chunk->map[run_pageind]; 1549e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1550e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(arena_run_tree_search(&bin->runs, run_mapelm) == 1551e476f8a161d445211fd6e54fe370275196e66bcbJason Evans NULL); 1552e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_insert(&bin->runs, run_mapelm); 1553e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1554e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1555e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1556e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1557e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (size <= small_maxclass) { 1558e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_small -= size; 1559e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.ndalloc_small++; 1560e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1561e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_medium -= size; 1562e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.ndalloc_medium++; 1563e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1564e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1565e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1566e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1567e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1568e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid 1569b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty, 1570b34e8684ec025aa780997c11f847c19fb269755bJason Evans arena_stats_t *astats, malloc_bin_stats_t *bstats, 1571b34e8684ec025aa780997c11f847c19fb269755bJason Evans malloc_large_stats_t *lstats) 1572b34e8684ec025aa780997c11f847c19fb269755bJason Evans{ 1573b34e8684ec025aa780997c11f847c19fb269755bJason Evans unsigned i, nlclasses; 1574b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1575b34e8684ec025aa780997c11f847c19fb269755bJason Evans *nactive += arena->nactive; 1576b34e8684ec025aa780997c11f847c19fb269755bJason Evans *ndirty += arena->ndirty; 1577b34e8684ec025aa780997c11f847c19fb269755bJason Evans 15784201af05425b69ee37ffca437aca0cdd604d1e51Jason Evans astats->mapped += arena->stats.mapped; 1579b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->npurge += arena->stats.npurge; 1580b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->nmadvise += arena->stats.nmadvise; 1581b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->purged += arena->stats.purged; 1582b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_small += arena->stats.allocated_small; 1583b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->nmalloc_small += arena->stats.nmalloc_small; 1584b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_small += arena->stats.ndalloc_small; 1585b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_medium += arena->stats.allocated_medium; 1586b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->nmalloc_medium += arena->stats.nmalloc_medium; 1587b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_medium += arena->stats.ndalloc_medium; 1588b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_large += arena->stats.allocated_large; 1589b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->nmalloc_large += arena->stats.nmalloc_large; 1590b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_large += arena->stats.ndalloc_large; 1591b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1592b34e8684ec025aa780997c11f847c19fb269755bJason Evans for (i = 0; i < nbins; i++) { 1593b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].nrequests += arena->bins[i].stats.nrequests; 1594b34e8684ec025aa780997c11f847c19fb269755bJason Evans#ifdef JEMALLOC_TCACHE 1595b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].nfills += arena->bins[i].stats.nfills; 1596b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].nflushes += arena->bins[i].stats.nflushes; 1597b34e8684ec025aa780997c11f847c19fb269755bJason Evans#endif 1598b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].nruns += arena->bins[i].stats.nruns; 1599b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].reruns += arena->bins[i].stats.reruns; 1600b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].highruns += arena->bins[i].stats.highruns; 1601b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].curruns += arena->bins[i].stats.curruns; 1602b34e8684ec025aa780997c11f847c19fb269755bJason Evans } 1603b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1604b34e8684ec025aa780997c11f847c19fb269755bJason Evans for (i = 0, nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT; 1605b34e8684ec025aa780997c11f847c19fb269755bJason Evans i < nlclasses; 1606b34e8684ec025aa780997c11f847c19fb269755bJason Evans i++) { 1607b34e8684ec025aa780997c11f847c19fb269755bJason Evans lstats[i].nrequests += arena->stats.lstats[i].nrequests; 1608b34e8684ec025aa780997c11f847c19fb269755bJason Evans lstats[i].highruns += arena->stats.lstats[i].highruns; 1609b34e8684ec025aa780997c11f847c19fb269755bJason Evans lstats[i].curruns += arena->stats.lstats[i].curruns; 1610b34e8684ec025aa780997c11f847c19fb269755bJason Evans } 1611b34e8684ec025aa780997c11f847c19fb269755bJason Evans} 1612b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1613b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void 1614b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_aprint(size_t nactive, size_t ndirty, const arena_stats_t *astats, 1615ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans void (*write4)(void *, const char *, const char *, const char *, 1616ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans const char *), void *w4opaque) 1617e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1618e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1619ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 1620bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans "dirty pages: %zu:%zu active:dirty, %"PRIu64" sweep%s," 1621bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans " %"PRIu64" madvise%s, %"PRIu64" purged\n", 1622b34e8684ec025aa780997c11f847c19fb269755bJason Evans nactive, ndirty, 1623b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->npurge, astats->npurge == 1 ? "" : "s", 1624b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->nmadvise, astats->nmadvise == 1 ? "" : "s", 1625b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->purged); 1626e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1627ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 162800b5c9334701d10a798ae86cd142df882f28519cJason Evans " allocated nmalloc ndalloc\n"); 1629bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans malloc_cprintf(write4, w4opaque, 1630bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans "small: %12zu %12"PRIu64" %12"PRIu64"\n", 1631b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_small, astats->nmalloc_small, 1632b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_small); 1633bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans malloc_cprintf(write4, w4opaque, 1634bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans "medium: %12zu %12"PRIu64" %12"PRIu64"\n", 1635b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_medium, astats->nmalloc_medium, 1636b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_medium); 1637bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans malloc_cprintf(write4, w4opaque, 1638bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans "large: %12zu %12"PRIu64" %12"PRIu64"\n", 1639b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_large, astats->nmalloc_large, 1640b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_large); 1641bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans malloc_cprintf(write4, w4opaque, 1642bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans "total: %12zu %12"PRIu64" %12"PRIu64"\n", 1643b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_small + astats->allocated_medium + 1644b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_large, astats->nmalloc_small + 1645b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->nmalloc_medium + astats->nmalloc_large, 1646b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_small + astats->ndalloc_medium + 1647b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_large); 1648ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, "mapped: %12zu\n", astats->mapped); 1649b34e8684ec025aa780997c11f847c19fb269755bJason Evans} 1650b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1651b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void 1652b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_bprint(arena_t *arena, const malloc_bin_stats_t *bstats, 1653ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans void (*write4)(void *, const char *, const char *, const char *, 1654ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans const char *), void *w4opaque) 1655b34e8684ec025aa780997c11f847c19fb269755bJason Evans{ 1656b34e8684ec025aa780997c11f847c19fb269755bJason Evans unsigned i, gap_start; 1657b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1658e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE 1659ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 1660b34e8684ec025aa780997c11f847c19fb269755bJason Evans "bins: bin size regs pgs requests " 1661b34e8684ec025aa780997c11f847c19fb269755bJason Evans "nfills nflushes newruns reruns maxruns curruns\n"); 1662e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#else 1663ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 1664b34e8684ec025aa780997c11f847c19fb269755bJason Evans "bins: bin size regs pgs requests " 1665b34e8684ec025aa780997c11f847c19fb269755bJason Evans "newruns reruns maxruns curruns\n"); 1666e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1667b34e8684ec025aa780997c11f847c19fb269755bJason Evans for (i = 0, gap_start = UINT_MAX; i < nbins; i++) { 1668b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (bstats[i].nruns == 0) { 1669b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (gap_start == UINT_MAX) 1670b34e8684ec025aa780997c11f847c19fb269755bJason Evans gap_start = i; 1671b34e8684ec025aa780997c11f847c19fb269755bJason Evans } else { 1672b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (gap_start != UINT_MAX) { 1673b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (i > gap_start + 1) { 1674b34e8684ec025aa780997c11f847c19fb269755bJason Evans /* Gap of more than one size class. */ 1675ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 1676b34e8684ec025aa780997c11f847c19fb269755bJason Evans "[%u..%u]\n", gap_start, 1677b34e8684ec025aa780997c11f847c19fb269755bJason Evans i - 1); 1678b34e8684ec025aa780997c11f847c19fb269755bJason Evans } else { 1679b34e8684ec025aa780997c11f847c19fb269755bJason Evans /* Gap of one size class. */ 1680ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 1681ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans "[%u]\n", gap_start); 1682e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1683b34e8684ec025aa780997c11f847c19fb269755bJason Evans gap_start = UINT_MAX; 1684b34e8684ec025aa780997c11f847c19fb269755bJason Evans } 1685ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 1686bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans "%13u %1s %5u %4u %3u %9"PRIu64" %9"PRIu64 1687e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE 1688bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans " %9"PRIu64" %9"PRIu64"" 1689e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1690bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans " %9"PRIu64" %7zu %7zu\n", 1691b34e8684ec025aa780997c11f847c19fb269755bJason Evans i, 1692b34e8684ec025aa780997c11f847c19fb269755bJason Evans i < ntbins ? "T" : i < ntbins + nqbins ? 1693b34e8684ec025aa780997c11f847c19fb269755bJason Evans "Q" : i < ntbins + nqbins + ncbins ? "C" : 1694b34e8684ec025aa780997c11f847c19fb269755bJason Evans i < ntbins + nqbins + ncbins + nsbins ? "S" 1695b34e8684ec025aa780997c11f847c19fb269755bJason Evans : "M", 1696b34e8684ec025aa780997c11f847c19fb269755bJason Evans arena->bins[i].reg_size, 1697b34e8684ec025aa780997c11f847c19fb269755bJason Evans arena->bins[i].nregs, 1698b34e8684ec025aa780997c11f847c19fb269755bJason Evans arena->bins[i].run_size >> PAGE_SHIFT, 1699b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].nrequests, 1700e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TCACHE 1701b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].nfills, 1702b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].nflushes, 1703e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1704b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].nruns, 1705b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].reruns, 1706b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].highruns, 1707b34e8684ec025aa780997c11f847c19fb269755bJason Evans bstats[i].curruns); 1708e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1709b34e8684ec025aa780997c11f847c19fb269755bJason Evans } 1710b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (gap_start != UINT_MAX) { 1711b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (i > gap_start + 1) { 1712b34e8684ec025aa780997c11f847c19fb269755bJason Evans /* Gap of more than one size class. */ 1713ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, "[%u..%u]\n", 1714ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans gap_start, i - 1); 1715b34e8684ec025aa780997c11f847c19fb269755bJason Evans } else { 1716b34e8684ec025aa780997c11f847c19fb269755bJason Evans /* Gap of one size class. */ 1717ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, "[%u]\n", gap_start); 1718e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1719e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1720b34e8684ec025aa780997c11f847c19fb269755bJason Evans} 1721e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1722b34e8684ec025aa780997c11f847c19fb269755bJason Evansstatic void 1723b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_lprint(const malloc_large_stats_t *lstats, 1724ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans void (*write4)(void *, const char *, const char *, const char *, 1725ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans const char *), void *w4opaque) 1726b34e8684ec025aa780997c11f847c19fb269755bJason Evans{ 1727b34e8684ec025aa780997c11f847c19fb269755bJason Evans size_t i; 1728b34e8684ec025aa780997c11f847c19fb269755bJason Evans ssize_t gap_start; 1729b34e8684ec025aa780997c11f847c19fb269755bJason Evans size_t nlclasses = (chunksize - PAGE_SIZE) >> PAGE_SHIFT; 1730b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1731ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 1732b34e8684ec025aa780997c11f847c19fb269755bJason Evans "large: size pages nrequests maxruns curruns\n"); 1733b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1734b34e8684ec025aa780997c11f847c19fb269755bJason Evans for (i = 0, gap_start = -1; i < nlclasses; i++) { 1735b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (lstats[i].nrequests == 0) { 1736b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (gap_start == -1) 1737b34e8684ec025aa780997c11f847c19fb269755bJason Evans gap_start = i; 1738b34e8684ec025aa780997c11f847c19fb269755bJason Evans } else { 1739b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (gap_start != -1) { 1740ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, "[%zu]\n", 1741b34e8684ec025aa780997c11f847c19fb269755bJason Evans i - gap_start); 1742b34e8684ec025aa780997c11f847c19fb269755bJason Evans gap_start = -1; 1743e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1744ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, 1745bc25a47ee0e2ac8e10a94d5fa070f0dbbdeb7e7eJason Evans "%13zu %5zu %9"PRIu64" %9zu %9zu\n", 1746b34e8684ec025aa780997c11f847c19fb269755bJason Evans (i+1) << PAGE_SHIFT, i+1, 1747b34e8684ec025aa780997c11f847c19fb269755bJason Evans lstats[i].nrequests, 1748b34e8684ec025aa780997c11f847c19fb269755bJason Evans lstats[i].highruns, 1749b34e8684ec025aa780997c11f847c19fb269755bJason Evans lstats[i].curruns); 1750e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1751e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1752b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (gap_start != -1) 1753ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans malloc_cprintf(write4, w4opaque, "[%zu]\n", i - gap_start); 1754b34e8684ec025aa780997c11f847c19fb269755bJason Evans} 1755b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1756b34e8684ec025aa780997c11f847c19fb269755bJason Evansvoid 1757b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_mprint(arena_t *arena, size_t nactive, size_t ndirty, 1758b34e8684ec025aa780997c11f847c19fb269755bJason Evans const arena_stats_t *astats, const malloc_bin_stats_t *bstats, 1759b34e8684ec025aa780997c11f847c19fb269755bJason Evans const malloc_large_stats_t *lstats, bool bins, bool large, 1760ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans void (*write4)(void *, const char *, const char *, const char *, 1761ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans const char *), void *w4opaque) 1762b34e8684ec025aa780997c11f847c19fb269755bJason Evans{ 1763b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1764ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans arena_stats_aprint(nactive, ndirty, astats, write4, w4opaque); 1765b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (bins && astats->nmalloc_small + astats->nmalloc_medium > 0) 1766ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans arena_stats_bprint(arena, bstats, write4, w4opaque); 1767b34e8684ec025aa780997c11f847c19fb269755bJason Evans if (large && astats->nmalloc_large > 0) 1768ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans arena_stats_lprint(lstats, write4, w4opaque); 1769b34e8684ec025aa780997c11f847c19fb269755bJason Evans} 1770b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1771b34e8684ec025aa780997c11f847c19fb269755bJason Evansvoid 1772b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_print(arena_t *arena, bool bins, bool large, 1773ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans void (*write4)(void *, const char *, const char *, const char *, 1774ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans const char *), void *w4opaque) 1775b34e8684ec025aa780997c11f847c19fb269755bJason Evans{ 1776b34e8684ec025aa780997c11f847c19fb269755bJason Evans size_t nactive, ndirty; 1777b34e8684ec025aa780997c11f847c19fb269755bJason Evans arena_stats_t astats; 1778b34e8684ec025aa780997c11f847c19fb269755bJason Evans malloc_bin_stats_t bstats[nbins]; 1779b34e8684ec025aa780997c11f847c19fb269755bJason Evans malloc_large_stats_t lstats[((chunksize - PAGE_SIZE) >> PAGE_SHIFT)]; 1780b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1781b34e8684ec025aa780997c11f847c19fb269755bJason Evans nactive = 0; 1782b34e8684ec025aa780997c11f847c19fb269755bJason Evans ndirty = 0; 1783b34e8684ec025aa780997c11f847c19fb269755bJason Evans memset(&astats, 0, sizeof(astats)); 1784b34e8684ec025aa780997c11f847c19fb269755bJason Evans memset(bstats, 0, sizeof(bstats)); 1785b34e8684ec025aa780997c11f847c19fb269755bJason Evans memset(lstats, 0, sizeof(lstats)); 1786b34e8684ec025aa780997c11f847c19fb269755bJason Evans 1787b34e8684ec025aa780997c11f847c19fb269755bJason Evans arena_stats_merge(arena, &nactive, &ndirty, &astats, bstats, lstats); 1788b34e8684ec025aa780997c11f847c19fb269755bJason Evans arena_stats_mprint(arena, nactive, ndirty, &astats, bstats, lstats, 1789ed1bf457fb90322d5a9fe9c78540cd8649b6b913Jason Evans bins, large, write4, w4opaque); 1790e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1791e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1792e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1793e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid 1794e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr) 1795e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1796e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Large allocation. */ 1797e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1798e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1799e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1800e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifndef JEMALLOC_STATS 1801e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk) 1802e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1803e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1804e476f8a161d445211fd6e54fe370275196e66bcbJason Evans { 1805e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#if (defined(JEMALLOC_FILL) || defined(JEMALLOC_STATS)) 1806e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> 1807e476f8a161d445211fd6e54fe370275196e66bcbJason Evans PAGE_SHIFT; 1808e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t size = chunk->map[pageind].bits & ~PAGE_MASK; 1809e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1810e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1811e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1812e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1813e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk) 1814e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1815e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ptr, 0x5a, size); 1816e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1817e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1818e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_large -= size; 1819e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[(size >> PAGE_SHIFT) - 1].curruns--; 1820e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1821e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1822e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1823e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.ndalloc_large++; 1824e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1825e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1826e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_dalloc(arena, (arena_run_t *)ptr, true); 1827e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1828e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1829e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1830e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 1831e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr, 1832e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t size, size_t oldsize) 1833e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1834e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1835e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size < oldsize); 1836e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1837e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1838e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Shrink the run, and make trailing pages available for other 1839e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * allocations. 1840e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1841e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1842e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size, 1843e476f8a161d445211fd6e54fe370275196e66bcbJason Evans true); 1844e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1845e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_large -= oldsize - size; 1846e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].nrequests++; 1847e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].curruns++; 1848e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->stats.lstats[size >> PAGE_SHIFT].curruns > 1849e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].highruns) { 1850e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].highruns = 1851e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].curruns; 1852e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1853e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[oldsize >> PAGE_SHIFT].curruns--; 1854e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1855e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1856e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1857e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1858e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool 1859e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, 1860e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t size, size_t oldsize) 1861e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1862e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> PAGE_SHIFT; 1863e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t npages = oldsize >> PAGE_SHIFT; 1864e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1865e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(oldsize == (chunk->map[pageind].bits & ~PAGE_MASK)); 1866e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1867e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Try to extend the run. */ 1868e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size > oldsize); 1869e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1870e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (pageind + npages < chunk_npages && (chunk->map[pageind+npages].bits 1871e476f8a161d445211fd6e54fe370275196e66bcbJason Evans & CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[pageind+npages].bits & 1872e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ~PAGE_MASK) >= size - oldsize) { 1873e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1874e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * The next run is available and sufficiently large. Split the 1875e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * following run, then merge the first part with the existing 1876e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * allocation. 1877e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1878e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk + 1879e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ((pageind+npages) << PAGE_SHIFT)), size - oldsize, true, 1880e476f8a161d445211fd6e54fe370275196e66bcbJason Evans false); 1881e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1882e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[pageind].bits = size | CHUNK_MAP_LARGE | 1883e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_ALLOCATED; 1884e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->map[pageind+npages].bits = CHUNK_MAP_LARGE | 1885e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_ALLOCATED; 1886e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1887e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 1888e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.allocated_large += size - oldsize; 1889e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].nrequests++; 1890e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].curruns++; 1891e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->stats.lstats[size >> PAGE_SHIFT].curruns > 1892e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].highruns) { 1893e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].highruns = 1894e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[size >> PAGE_SHIFT].curruns; 1895e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1896e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats[oldsize >> PAGE_SHIFT].curruns--; 1897e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1898e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1899e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 1900e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1901e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1902e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1903e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (true); 1904e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1905e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1906e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 1907e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Try to resize a large allocation, in order to avoid copying. This will 1908e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * always fail if growing an object, and the following run is already in use. 1909e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1910e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool 1911e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large(void *ptr, size_t size, size_t oldsize) 1912e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1913e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t psize; 1914e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1915e476f8a161d445211fd6e54fe370275196e66bcbJason Evans psize = PAGE_CEILING(size); 1916e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (psize == oldsize) { 1917e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Same size class. */ 1918e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1919e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk && size < oldsize) { 1920e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - 1921e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size); 1922e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1923e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1924e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 1925e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1926e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 1927e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_t *arena; 1928e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1929e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 1930e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena = chunk->arena; 1931e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(arena->magic == ARENA_MAGIC); 1932e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1933e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (psize < oldsize) { 1934e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1935e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Fill before shrinking in order avoid a race. */ 1936e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk) { 1937e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)ptr + size), 0x5a, 1938e476f8a161d445211fd6e54fe370275196e66bcbJason Evans oldsize - size); 1939e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1940e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1941e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_ralloc_large_shrink(arena, chunk, ptr, psize, 1942e476f8a161d445211fd6e54fe370275196e66bcbJason Evans oldsize); 1943e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 1944e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1945e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool ret = arena_ralloc_large_grow(arena, chunk, ptr, 1946e476f8a161d445211fd6e54fe370275196e66bcbJason Evans psize, oldsize); 1947e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 1948e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == false && opt_zero) { 1949e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)ptr + oldsize), 0, 1950e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size - oldsize); 1951e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1952e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 1953e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1954e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1955e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1956e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1957e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1958e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 1959e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc(void *ptr, size_t size, size_t oldsize) 1960e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1961e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 1962e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t copysize; 1963e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1964e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1965e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Try to avoid moving the allocation. 1966e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 1967e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * posix_memalign() can cause allocation of "large" objects that are 1968e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * smaller than bin_maxclass (in order to meet alignment requirements). 1969e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Therefore, do not assume that (oldsize <= bin_maxclass) indicates 1970e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * ptr refers to a bin-allocated object. 1971e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1972e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (oldsize <= arena_maxclass) { 1973e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena_is_large(ptr) == false ) { 1974e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (size <= small_maxclass) { 1975e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (oldsize <= small_maxclass && 1976e476f8a161d445211fd6e54fe370275196e66bcbJason Evans small_size2bin[size] == 1977e476f8a161d445211fd6e54fe370275196e66bcbJason Evans small_size2bin[oldsize]) 1978e476f8a161d445211fd6e54fe370275196e66bcbJason Evans goto IN_PLACE; 1979e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else if (size <= bin_maxclass) { 1980e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (small_maxclass < oldsize && oldsize <= 1981e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin_maxclass && MEDIUM_CEILING(size) == 1982e476f8a161d445211fd6e54fe370275196e66bcbJason Evans MEDIUM_CEILING(oldsize)) 1983e476f8a161d445211fd6e54fe370275196e66bcbJason Evans goto IN_PLACE; 1984e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1985e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1986e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size <= arena_maxclass); 1987e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (size > bin_maxclass) { 1988e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena_ralloc_large(ptr, size, oldsize) == 1989e476f8a161d445211fd6e54fe370275196e66bcbJason Evans false) 1990e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ptr); 1991e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1992e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1993e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1994e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1995e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Try to avoid moving the allocation. */ 1996e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (size <= small_maxclass) { 1997e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (oldsize <= small_maxclass && small_size2bin[size] == 1998e476f8a161d445211fd6e54fe370275196e66bcbJason Evans small_size2bin[oldsize]) 1999e476f8a161d445211fd6e54fe370275196e66bcbJason Evans goto IN_PLACE; 2000e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else if (size <= bin_maxclass) { 2001e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (small_maxclass < oldsize && oldsize <= bin_maxclass && 2002e476f8a161d445211fd6e54fe370275196e66bcbJason Evans MEDIUM_CEILING(size) == MEDIUM_CEILING(oldsize)) 2003e476f8a161d445211fd6e54fe370275196e66bcbJason Evans goto IN_PLACE; 2004e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 2005e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (bin_maxclass < oldsize && oldsize <= arena_maxclass) { 2006e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size > bin_maxclass); 2007e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena_ralloc_large(ptr, size, oldsize) == false) 2008e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ptr); 2009e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2010e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2011e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2012e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 2013e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * If we get here, then size and oldsize are different enough that we 2014e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * need to move the object. In that case, fall back to allocating new 2015e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * space and copying. 2016e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 2017e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = arena_malloc(size, false); 2018e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == NULL) 2019e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 2020e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2021e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Junk/zero-filling were already done by arena_malloc(). */ 2022e476f8a161d445211fd6e54fe370275196e66bcbJason Evans copysize = (size < oldsize) ? size : oldsize; 2023e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memcpy(ret, ptr, copysize); 2024e476f8a161d445211fd6e54fe370275196e66bcbJason Evans idalloc(ptr); 2025e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 2026e476f8a161d445211fd6e54fe370275196e66bcbJason EvansIN_PLACE: 2027e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_FILL 2028e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_junk && size < oldsize) 2029e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - size); 2030e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else if (opt_zero && size > oldsize) 2031e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)ptr + oldsize), 0, size - oldsize); 2032e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2033e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ptr); 2034e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 2035e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2036e476f8a161d445211fd6e54fe370275196e66bcbJason Evansbool 2037e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_new(arena_t *arena, unsigned ind) 2038e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 2039e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned i; 2040e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin; 2041e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t prev_run_size; 2042e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2043e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (malloc_mutex_init(&arena->lock)) 2044e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (true); 2045e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2046e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 2047e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(&arena->stats, 0, sizeof(arena_stats_t)); 2048e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->stats.lstats = (malloc_large_stats_t *)base_alloc( 2049e476f8a161d445211fd6e54fe370275196e66bcbJason Evans sizeof(malloc_large_stats_t) * ((chunksize - PAGE_SIZE) >> 2050e476f8a161d445211fd6e54fe370275196e66bcbJason Evans PAGE_SHIFT)); 2051e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->stats.lstats == NULL) 2052e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (true); 2053e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(arena->stats.lstats, 0, sizeof(malloc_large_stats_t) * 2054e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ((chunksize - PAGE_SIZE) >> PAGE_SHIFT)); 2055e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# ifdef JEMALLOC_TCACHE 2056e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ql_new(&arena->tcache_ql); 2057e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# endif 2058e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2059e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2060e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TRACE 2061e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_trace) { 2062e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* "jemtr.<pid>.<arena>" */ 2063e476f8a161d445211fd6e54fe370275196e66bcbJason Evans char buf[UMAX2S_BUFSIZE]; 2064e476f8a161d445211fd6e54fe370275196e66bcbJason Evans char filename[6 + UMAX2S_BUFSIZE + 1 + UMAX2S_BUFSIZE + 1]; 2065e476f8a161d445211fd6e54fe370275196e66bcbJason Evans char *s; 2066e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned i, slen; 2067e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2068e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->trace_buf_end = 0; 2069e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2070e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i = 0; 2071e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2072e476f8a161d445211fd6e54fe370275196e66bcbJason Evans s = "jemtr."; 2073e476f8a161d445211fd6e54fe370275196e66bcbJason Evans slen = strlen(s); 2074e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memcpy(&filename[i], s, slen); 2075e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i += slen; 2076e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2077e476f8a161d445211fd6e54fe370275196e66bcbJason Evans s = umax2s(getpid(), 10, buf); 2078e476f8a161d445211fd6e54fe370275196e66bcbJason Evans slen = strlen(s); 2079e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memcpy(&filename[i], s, slen); 2080e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i += slen; 2081e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2082e476f8a161d445211fd6e54fe370275196e66bcbJason Evans s = "."; 2083e476f8a161d445211fd6e54fe370275196e66bcbJason Evans slen = strlen(s); 2084e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memcpy(&filename[i], s, slen); 2085e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i += slen; 2086e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2087e476f8a161d445211fd6e54fe370275196e66bcbJason Evans s = umax2s(ind, 10, buf); 2088e476f8a161d445211fd6e54fe370275196e66bcbJason Evans slen = strlen(s); 2089e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memcpy(&filename[i], s, slen); 2090e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i += slen; 2091e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2092e476f8a161d445211fd6e54fe370275196e66bcbJason Evans filename[i] = '\0'; 2093e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2094e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->trace_fd = creat(filename, 0644); 2095e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->trace_fd == -1) { 2096e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_write4("<jemalloc>", 2097e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ": creat(\"", filename, "\", O_RDWR) failed\n"); 2098e476f8a161d445211fd6e54fe370275196e66bcbJason Evans abort(); 2099e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2100e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2101e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2102e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2103e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Initialize chunks. */ 2104e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_tree_dirty_new(&arena->chunks_dirty); 2105e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->spare = NULL; 2106e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2107e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->nactive = 0; 2108e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty = 0; 2109e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2110e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_avail_tree_new(&arena->runs_avail); 2111e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2112e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Initialize bins. */ 2113e476f8a161d445211fd6e54fe370275196e66bcbJason Evans prev_run_size = PAGE_SIZE; 2114e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2115e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i = 0; 2116e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY 2117e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* (2^n)-spaced tiny bins. */ 2118e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < ntbins; i++) { 2119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[i]; 2120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = NULL; 2121e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_new(&bin->runs); 2122e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2123e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size = (1U << (LG_TINY_MIN + i)); 2124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2125e476f8a161d445211fd6e54fe370275196e66bcbJason Evans prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); 2126e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2127e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 2128e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 2129e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2130e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2131e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2132e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2133e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Quantum-spaced bins. */ 2134e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < ntbins + nqbins; i++) { 2135e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[i]; 2136e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = NULL; 2137e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_new(&bin->runs); 2138e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2139e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size = (i - ntbins + 1) << LG_QUANTUM; 2140e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2141e476f8a161d445211fd6e54fe370275196e66bcbJason Evans prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); 2142e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2143e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 2144e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 2145e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2146e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2147e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2148e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Cacheline-spaced bins. */ 2149e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < ntbins + nqbins + ncbins; i++) { 2150e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[i]; 2151e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = NULL; 2152e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_new(&bin->runs); 2153e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2154e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size = cspace_min + ((i - (ntbins + nqbins)) << 2155e476f8a161d445211fd6e54fe370275196e66bcbJason Evans LG_CACHELINE); 2156e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2157e476f8a161d445211fd6e54fe370275196e66bcbJason Evans prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); 2158e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2159e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 2160e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 2161e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2162e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2163e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2164e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Subpage-spaced bins. */ 2165e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < ntbins + nqbins + ncbins + nsbins; i++) { 2166e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[i]; 2167e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = NULL; 2168e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_new(&bin->runs); 2169e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2170e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size = sspace_min + ((i - (ntbins + nqbins + ncbins)) 2171e476f8a161d445211fd6e54fe370275196e66bcbJason Evans << LG_SUBPAGE); 2172e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2173e476f8a161d445211fd6e54fe370275196e66bcbJason Evans prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); 2174e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2175e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 2176e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 2177e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2178e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2179e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2180e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Medium bins. */ 2181e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < nbins; i++) { 2182e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[i]; 2183e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = NULL; 2184e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_new(&bin->runs); 2185e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2186e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->reg_size = medium_min + ((i - (ntbins + nqbins + ncbins + 2187e476f8a161d445211fd6e54fe370275196e66bcbJason Evans nsbins)) << lg_mspace); 2188e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2189e476f8a161d445211fd6e54fe370275196e66bcbJason Evans prev_run_size = arena_bin_run_size_calc(bin, prev_run_size); 2190e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2191e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_STATS 2192e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 2193e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2194e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2195e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2196e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG 2197e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->magic = ARENA_MAGIC; 2198e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2199e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2200e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 2201e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 2202e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2203e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY 2204e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Compute the smallest power of 2 that is >= x. */ 2205e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic size_t 2206e476f8a161d445211fd6e54fe370275196e66bcbJason Evanspow2_ceil(size_t x) 2207e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 2208e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2209e476f8a161d445211fd6e54fe370275196e66bcbJason Evans x--; 2210e476f8a161d445211fd6e54fe370275196e66bcbJason Evans x |= x >> 1; 2211e476f8a161d445211fd6e54fe370275196e66bcbJason Evans x |= x >> 2; 2212e476f8a161d445211fd6e54fe370275196e66bcbJason Evans x |= x >> 4; 2213e476f8a161d445211fd6e54fe370275196e66bcbJason Evans x |= x >> 8; 2214e476f8a161d445211fd6e54fe370275196e66bcbJason Evans x |= x >> 16; 2215e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#if (SIZEOF_PTR == 8) 2216e476f8a161d445211fd6e54fe370275196e66bcbJason Evans x |= x >> 32; 2217e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2218e476f8a161d445211fd6e54fe370275196e66bcbJason Evans x++; 2219e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (x); 2220e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 2221e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2222e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2223e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG 2224e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 2225e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssmall_size2bin_validate(void) 2226e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 2227e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t i, size, binind; 2228e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2229e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(small_size2bin[0] == 0xffU); 2230e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i = 1; 2231e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# ifdef JEMALLOC_TINY 2232e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Tiny. */ 2233e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < (1U << LG_TINY_MIN); i++) { 2234e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = pow2_ceil(1U << LG_TINY_MIN); 2235e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ffs((int)(size >> (LG_TINY_MIN + 1))); 2236e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(small_size2bin[i] == binind); 2237e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2238e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < qspace_min; i++) { 2239e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = pow2_ceil(i); 2240e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ffs((int)(size >> (LG_TINY_MIN + 1))); 2241e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(small_size2bin[i] == binind); 2242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2243e476f8a161d445211fd6e54fe370275196e66bcbJason Evans# endif 2244e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Quantum-spaced. */ 2245e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i <= qspace_max; i++) { 2246e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = QUANTUM_CEILING(i); 2247e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ntbins + (size >> LG_QUANTUM) - 1; 2248e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(small_size2bin[i] == binind); 2249e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2250e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Cacheline-spaced. */ 2251e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i <= cspace_max; i++) { 2252e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = CACHELINE_CEILING(i); 2253e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ntbins + nqbins + ((size - cspace_min) >> 2254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans LG_CACHELINE); 2255e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(small_size2bin[i] == binind); 2256e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2257e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Sub-page. */ 2258e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i <= sspace_max; i++) { 2259e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = SUBPAGE_CEILING(i); 2260e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ntbins + nqbins + ncbins + ((size - sspace_min) 2261e476f8a161d445211fd6e54fe370275196e66bcbJason Evans >> LG_SUBPAGE); 2262e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(small_size2bin[i] == binind); 2263e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2264e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 2265e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2266e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2267e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool 2268e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssmall_size2bin_init(void) 2269e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 2270e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2271e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT 2272e476f8a161d445211fd6e54fe370275196e66bcbJason Evans || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT 2273e476f8a161d445211fd6e54fe370275196e66bcbJason Evans || sizeof(const_small_size2bin) != small_maxclass + 1) 2274e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (small_size2bin_init_hard()); 2275e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2276e476f8a161d445211fd6e54fe370275196e66bcbJason Evans small_size2bin = const_small_size2bin; 2277e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG 2278e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(sizeof(const_small_size2bin) == small_maxclass + 1); 2279e476f8a161d445211fd6e54fe370275196e66bcbJason Evans small_size2bin_validate(); 2280e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2281e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 2282e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 2283e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2284e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool 2285e476f8a161d445211fd6e54fe370275196e66bcbJason Evanssmall_size2bin_init_hard(void) 2286e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 2287e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t i, size, binind; 2288e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uint8_t *custom_small_size2bin; 2289e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2290e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(opt_lg_qspace_max != LG_QSPACE_MAX_DEFAULT 2291e476f8a161d445211fd6e54fe370275196e66bcbJason Evans || opt_lg_cspace_max != LG_CSPACE_MAX_DEFAULT 2292e476f8a161d445211fd6e54fe370275196e66bcbJason Evans || sizeof(const_small_size2bin) != small_maxclass + 1); 2293e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2294e476f8a161d445211fd6e54fe370275196e66bcbJason Evans custom_small_size2bin = (uint8_t *)base_alloc(small_maxclass + 1); 2295e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (custom_small_size2bin == NULL) 2296e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (true); 2297e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2298e476f8a161d445211fd6e54fe370275196e66bcbJason Evans custom_small_size2bin[0] = 0xffU; 2299e476f8a161d445211fd6e54fe370275196e66bcbJason Evans i = 1; 2300e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY 2301e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Tiny. */ 2302e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < (1U << LG_TINY_MIN); i++) { 2303e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = pow2_ceil(1U << LG_TINY_MIN); 2304e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ffs((int)(size >> (LG_TINY_MIN + 1))); 2305e476f8a161d445211fd6e54fe370275196e66bcbJason Evans custom_small_size2bin[i] = binind; 2306e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2307e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i < qspace_min; i++) { 2308e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = pow2_ceil(i); 2309e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ffs((int)(size >> (LG_TINY_MIN + 1))); 2310e476f8a161d445211fd6e54fe370275196e66bcbJason Evans custom_small_size2bin[i] = binind; 2311e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2312e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2313e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Quantum-spaced. */ 2314e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i <= qspace_max; i++) { 2315e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = QUANTUM_CEILING(i); 2316e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ntbins + (size >> LG_QUANTUM) - 1; 2317e476f8a161d445211fd6e54fe370275196e66bcbJason Evans custom_small_size2bin[i] = binind; 2318e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2319e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Cacheline-spaced. */ 2320e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i <= cspace_max; i++) { 2321e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = CACHELINE_CEILING(i); 2322e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ntbins + nqbins + ((size - cspace_min) >> 2323e476f8a161d445211fd6e54fe370275196e66bcbJason Evans LG_CACHELINE); 2324e476f8a161d445211fd6e54fe370275196e66bcbJason Evans custom_small_size2bin[i] = binind; 2325e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2326e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Sub-page. */ 2327e476f8a161d445211fd6e54fe370275196e66bcbJason Evans for (; i <= sspace_max; i++) { 2328e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = SUBPAGE_CEILING(i); 2329e476f8a161d445211fd6e54fe370275196e66bcbJason Evans binind = ntbins + nqbins + ncbins + ((size - sspace_min) >> 2330e476f8a161d445211fd6e54fe370275196e66bcbJason Evans LG_SUBPAGE); 2331e476f8a161d445211fd6e54fe370275196e66bcbJason Evans custom_small_size2bin[i] = binind; 2332e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2333e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2334e476f8a161d445211fd6e54fe370275196e66bcbJason Evans small_size2bin = custom_small_size2bin; 2335e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_DEBUG 2336e476f8a161d445211fd6e54fe370275196e66bcbJason Evans small_size2bin_validate(); 2337e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 2339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 2340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2341e476f8a161d445211fd6e54fe370275196e66bcbJason Evansbool 2342e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_boot0(void) 2343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 2344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Set variables according to the value of opt_lg_[qc]space_max. */ 2346e476f8a161d445211fd6e54fe370275196e66bcbJason Evans qspace_max = (1U << opt_lg_qspace_max); 2347e476f8a161d445211fd6e54fe370275196e66bcbJason Evans cspace_min = CACHELINE_CEILING(qspace_max); 2348e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (cspace_min == qspace_max) 2349e476f8a161d445211fd6e54fe370275196e66bcbJason Evans cspace_min += CACHELINE; 2350e476f8a161d445211fd6e54fe370275196e66bcbJason Evans cspace_max = (1U << opt_lg_cspace_max); 2351e476f8a161d445211fd6e54fe370275196e66bcbJason Evans sspace_min = SUBPAGE_CEILING(cspace_max); 2352e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (sspace_min == cspace_max) 2353e476f8a161d445211fd6e54fe370275196e66bcbJason Evans sspace_min += SUBPAGE; 2354e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(sspace_min < PAGE_SIZE); 2355e476f8a161d445211fd6e54fe370275196e66bcbJason Evans sspace_max = PAGE_SIZE - SUBPAGE; 2356e476f8a161d445211fd6e54fe370275196e66bcbJason Evans medium_max = (1U << opt_lg_medium_max); 2357e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2358e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#ifdef JEMALLOC_TINY 2359e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(LG_QUANTUM >= LG_TINY_MIN); 2360e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#endif 2361e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(ntbins <= LG_QUANTUM); 2362e476f8a161d445211fd6e54fe370275196e66bcbJason Evans nqbins = qspace_max >> LG_QUANTUM; 2363e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ncbins = ((cspace_max - cspace_min) >> LG_CACHELINE) + 1; 2364e476f8a161d445211fd6e54fe370275196e66bcbJason Evans nsbins = ((sspace_max - sspace_min) >> LG_SUBPAGE) + 1; 2365e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2366e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 2367e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Compute medium size class spacing and the number of medium size 2368e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * classes. Limit spacing to no more than pagesize, but if possible 2369e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * use the smallest spacing that does not exceed NMBINS_MAX medium size 2370e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * classes. 2371e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 2372e476f8a161d445211fd6e54fe370275196e66bcbJason Evans lg_mspace = LG_SUBPAGE; 2373e476f8a161d445211fd6e54fe370275196e66bcbJason Evans nmbins = ((medium_max - medium_min) >> lg_mspace) + 1; 2374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans while (lg_mspace < PAGE_SHIFT && nmbins > NMBINS_MAX) { 2375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans lg_mspace = lg_mspace + 1; 2376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans nmbins = ((medium_max - medium_min) >> lg_mspace) + 1; 2377e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2378e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mspace_mask = (1U << lg_mspace) - 1U; 2379e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2380e476f8a161d445211fd6e54fe370275196e66bcbJason Evans mbin0 = ntbins + nqbins + ncbins + nsbins; 2381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans nbins = mbin0 + nmbins; 2382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 2383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * The small_size2bin lookup table uses uint8_t to encode each bin 2384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * index, so we cannot support more than 256 small size classes. This 2385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * limit is difficult to exceed (not even possible with 16B quantum and 2386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * 4KiB pages), and such configurations are impractical, but 2387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * nonetheless we need to protect against this case in order to avoid 2388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * undefined behavior. 2389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 2390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (mbin0 > 256) { 2391e476f8a161d445211fd6e54fe370275196e66bcbJason Evans char line_buf[UMAX2S_BUFSIZE]; 2392e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_write4("<jemalloc>: Too many small size classes (", 2393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans umax2s(mbin0, 10, line_buf), " > max 256)\n", ""); 2394e476f8a161d445211fd6e54fe370275196e66bcbJason Evans abort(); 2395e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 2396e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2397e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (small_size2bin_init()) 2398e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (true); 2399e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2400e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 2401e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 2402e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2403e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid 2404e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_boot1(void) 2405e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 2406e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t header_size; 2407e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2408e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 2409e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Compute the header size such that it is large enough to contain the 2410e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * page map. 2411e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 2412e476f8a161d445211fd6e54fe370275196e66bcbJason Evans header_size = sizeof(arena_chunk_t) + 2413e476f8a161d445211fd6e54fe370275196e66bcbJason Evans (sizeof(arena_chunk_map_t) * (chunk_npages - 1)); 2414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_header_npages = (header_size >> PAGE_SHIFT) + 2415e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ((header_size & PAGE_MASK) != 0); 2416e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_maxclass = chunksize - (arena_chunk_header_npages << PAGE_SHIFT); 2417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 2418