1*c43cad87SWarner Losh #include "jemalloc/internal/jemalloc_preamble.h" 2*c43cad87SWarner Losh #include "jemalloc/internal/jemalloc_internal_includes.h" 3*c43cad87SWarner Losh 4*c43cad87SWarner Losh #include "jemalloc/internal/bit_util.h" 5*c43cad87SWarner Losh #include "jemalloc/internal/cache_bin.h" 6*c43cad87SWarner Losh #include "jemalloc/internal/safety_check.h" 7*c43cad87SWarner Losh 8*c43cad87SWarner Losh void 9*c43cad87SWarner Losh cache_bin_info_init(cache_bin_info_t *info, 10*c43cad87SWarner Losh cache_bin_sz_t ncached_max) { 11*c43cad87SWarner Losh assert(ncached_max <= CACHE_BIN_NCACHED_MAX); 12*c43cad87SWarner Losh size_t stack_size = (size_t)ncached_max * sizeof(void *); 13*c43cad87SWarner Losh assert(stack_size < ((size_t)1 << (sizeof(cache_bin_sz_t) * 8))); 14*c43cad87SWarner Losh info->ncached_max = (cache_bin_sz_t)ncached_max; 15*c43cad87SWarner Losh } 16*c43cad87SWarner Losh 17*c43cad87SWarner Losh void 18*c43cad87SWarner Losh cache_bin_info_compute_alloc(cache_bin_info_t *infos, szind_t ninfos, 19*c43cad87SWarner Losh size_t *size, size_t *alignment) { 20*c43cad87SWarner Losh /* For the total bin stack region (per tcache), reserve 2 more slots so 21*c43cad87SWarner Losh * that 22*c43cad87SWarner Losh * 1) the empty position can be safely read on the fast path before 23*c43cad87SWarner Losh * checking "is_empty"; and 24*c43cad87SWarner Losh * 2) the cur_ptr can go beyond the empty position by 1 step safely on 25*c43cad87SWarner Losh * the fast path (i.e. no overflow). 26*c43cad87SWarner Losh */ 27*c43cad87SWarner Losh *size = sizeof(void *) * 2; 28*c43cad87SWarner Losh for (szind_t i = 0; i < ninfos; i++) { 29*c43cad87SWarner Losh assert(infos[i].ncached_max > 0); 30*c43cad87SWarner Losh *size += infos[i].ncached_max * sizeof(void *); 31*c43cad87SWarner Losh } 32*c43cad87SWarner Losh 33*c43cad87SWarner Losh /* 34*c43cad87SWarner Losh * Align to at least PAGE, to minimize the # of TLBs needed by the 35*c43cad87SWarner Losh * smaller sizes; also helps if the larger sizes don't get used at all. 36*c43cad87SWarner Losh */ 37*c43cad87SWarner Losh *alignment = PAGE; 38*c43cad87SWarner Losh } 39*c43cad87SWarner Losh 40*c43cad87SWarner Losh void 41*c43cad87SWarner Losh cache_bin_preincrement(cache_bin_info_t *infos, szind_t ninfos, void *alloc, 42*c43cad87SWarner Losh size_t *cur_offset) { 43*c43cad87SWarner Losh if (config_debug) { 44*c43cad87SWarner Losh size_t computed_size; 45*c43cad87SWarner Losh size_t computed_alignment; 46*c43cad87SWarner Losh 47*c43cad87SWarner Losh /* Pointer should be as aligned as we asked for. */ 48*c43cad87SWarner Losh cache_bin_info_compute_alloc(infos, ninfos, &computed_size, 49*c43cad87SWarner Losh &computed_alignment); 50*c43cad87SWarner Losh assert(((uintptr_t)alloc & (computed_alignment - 1)) == 0); 51*c43cad87SWarner Losh } 52*c43cad87SWarner Losh 53*c43cad87SWarner Losh *(uintptr_t *)((uintptr_t)alloc + *cur_offset) = 54*c43cad87SWarner Losh cache_bin_preceding_junk; 55*c43cad87SWarner Losh *cur_offset += sizeof(void *); 56*c43cad87SWarner Losh } 57*c43cad87SWarner Losh 58*c43cad87SWarner Losh void 59*c43cad87SWarner Losh cache_bin_postincrement(cache_bin_info_t *infos, szind_t ninfos, void *alloc, 60*c43cad87SWarner Losh size_t *cur_offset) { 61*c43cad87SWarner Losh *(uintptr_t *)((uintptr_t)alloc + *cur_offset) = 62*c43cad87SWarner Losh cache_bin_trailing_junk; 63*c43cad87SWarner Losh *cur_offset += sizeof(void *); 64*c43cad87SWarner Losh } 65*c43cad87SWarner Losh 66*c43cad87SWarner Losh void 67*c43cad87SWarner Losh cache_bin_init(cache_bin_t *bin, cache_bin_info_t *info, void *alloc, 68*c43cad87SWarner Losh size_t *cur_offset) { 69*c43cad87SWarner Losh /* 70*c43cad87SWarner Losh * The full_position points to the lowest available space. Allocations 71*c43cad87SWarner Losh * will access the slots toward higher addresses (for the benefit of 72*c43cad87SWarner Losh * adjacent prefetch). 73*c43cad87SWarner Losh */ 74*c43cad87SWarner Losh void *stack_cur = (void *)((uintptr_t)alloc + *cur_offset); 75*c43cad87SWarner Losh void *full_position = stack_cur; 76*c43cad87SWarner Losh uint16_t bin_stack_size = info->ncached_max * sizeof(void *); 77*c43cad87SWarner Losh 78*c43cad87SWarner Losh *cur_offset += bin_stack_size; 79*c43cad87SWarner Losh void *empty_position = (void *)((uintptr_t)alloc + *cur_offset); 80*c43cad87SWarner Losh 81*c43cad87SWarner Losh /* Init to the empty position. */ 82*c43cad87SWarner Losh bin->stack_head = (void **)empty_position; 83*c43cad87SWarner Losh bin->low_bits_low_water = (uint16_t)(uintptr_t)bin->stack_head; 84*c43cad87SWarner Losh bin->low_bits_full = (uint16_t)(uintptr_t)full_position; 85*c43cad87SWarner Losh bin->low_bits_empty = (uint16_t)(uintptr_t)empty_position; 86*c43cad87SWarner Losh cache_bin_sz_t free_spots = cache_bin_diff(bin, 87*c43cad87SWarner Losh bin->low_bits_full, (uint16_t)(uintptr_t)bin->stack_head, 88*c43cad87SWarner Losh /* racy */ false); 89*c43cad87SWarner Losh assert(free_spots == bin_stack_size); 90*c43cad87SWarner Losh assert(cache_bin_ncached_get_local(bin, info) == 0); 91*c43cad87SWarner Losh assert(cache_bin_empty_position_get(bin) == empty_position); 92*c43cad87SWarner Losh 93*c43cad87SWarner Losh assert(bin_stack_size > 0 || empty_position == full_position); 94*c43cad87SWarner Losh } 95*c43cad87SWarner Losh 96*c43cad87SWarner Losh bool 97*c43cad87SWarner Losh cache_bin_still_zero_initialized(cache_bin_t *bin) { 98*c43cad87SWarner Losh return bin->stack_head == NULL; 99*c43cad87SWarner Losh } 100