arena.c revision f54166e7ef5313c3b5c773cbb0ca2af95f5a15ae
1e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define JEMALLOC_ARENA_C_ 2376b1529a383c39adf4674baf6db83a5e63f97acJason Evans#include "jemalloc/internal/jemalloc_internal.h" 3e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 4e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/ 5e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Data. */ 6e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 7e476f8a161d445211fd6e54fe370275196e66bcbJason Evansssize_t opt_lg_dirty_mult = LG_DIRTY_MULT_DEFAULT; 8b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansarena_bin_info_t arena_bin_info[NBINS]; 9e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 10b172610317babc7f365584ddd7fdaf4eb8d9d04cJason EvansJEMALLOC_ATTR(aligned(CACHELINE)) 11b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansconst uint8_t small_size2bin[] = { 1241ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans#define S2B_8(i) i, 13e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_16(i) S2B_8(i) S2B_8(i) 14e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_32(i) S2B_16(i) S2B_16(i) 15e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_64(i) S2B_32(i) S2B_32(i) 16e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_128(i) S2B_64(i) S2B_64(i) 17e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#define S2B_256(i) S2B_128(i) S2B_128(i) 18b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define S2B_512(i) S2B_256(i) S2B_256(i) 19b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define S2B_1024(i) S2B_512(i) S2B_512(i) 20b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define S2B_2048(i) S2B_1024(i) S2B_1024(i) 21b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define S2B_4096(i) S2B_2048(i) S2B_2048(i) 22b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define S2B_8192(i) S2B_4096(i) S2B_4096(i) 23b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define SIZE_CLASS(bin, delta, size) \ 24b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans S2B_##delta(bin) 25b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans SIZE_CLASSES 26e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_8 27e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_16 28e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_32 29e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_64 30e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_128 31e476f8a161d445211fd6e54fe370275196e66bcbJason Evans#undef S2B_256 32b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_512 33b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_1024 34b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_2048 35b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_4096 36b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef S2B_8192 37b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef SIZE_CLASS 38b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans}; 39e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 40e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/ 41e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Function prototypes for non-inline static functions. */ 42e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 43e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_run_split(arena_t *arena, arena_run_t *run, size_t size, 44e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool large, bool zero); 45e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_chunk_t *arena_chunk_alloc(arena_t *arena); 46e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk); 47e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *arena_run_alloc(arena_t *arena, size_t size, bool large, 48e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool zero); 496005f0710cf07d60659d91b20b7ff5592d310027Jason Evansstatic void arena_purge(arena_t *arena, bool all); 50e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty); 51e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, 52e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run, size_t oldsize, size_t newsize); 53e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, 54e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run, size_t oldsize, size_t newsize, bool dirty); 55e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic arena_run_t *arena_bin_runs_first(arena_bin_t *bin); 56e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic void arena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run); 57e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic void arena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run); 58e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic arena_run_t *arena_bin_nonfull_run_tryget(arena_bin_t *bin); 59e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t *arena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin); 60e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void *arena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin); 61088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evansstatic void arena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run, 62088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans arena_bin_t *bin); 63e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, 64e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run, arena_bin_t *bin); 65940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansstatic void arena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, 66940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans arena_run_t *run, arena_bin_t *bin); 67e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void arena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, 688e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans void *ptr, size_t oldsize, size_t size); 69e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool arena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, 708e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans void *ptr, size_t oldsize, size_t size, size_t extra, bool zero); 718e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansstatic bool arena_ralloc_large(void *ptr, size_t oldsize, size_t size, 728e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans size_t extra, bool zero); 7349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansstatic size_t bin_info_run_size_calc(arena_bin_info_t *bin_info, 7449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t min_run_size); 75b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansstatic void bin_info_init(void); 76e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 77e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/******************************************************************************/ 78e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 79e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int 80e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) 81e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 82e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uintptr_t a_mapelm = (uintptr_t)a; 83e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uintptr_t b_mapelm = (uintptr_t)b; 84e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 85e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(a != NULL); 86e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(b != NULL); 87e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 88e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return ((a_mapelm > b_mapelm) - (a_mapelm < b_mapelm)); 89e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 90e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 91f3ff75289be32382fa455b4436871e4958fe6bf9Jason Evans/* Generate red-black tree functions. */ 927372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evansrb_gen(static UNUSED, arena_run_tree_, arena_run_tree_t, arena_chunk_map_t, 937372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans u.rb_link, arena_run_comp) 94e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 95e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline int 96e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_avail_comp(arena_chunk_map_t *a, arena_chunk_map_t *b) 97e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 98e476f8a161d445211fd6e54fe370275196e66bcbJason Evans int ret; 99e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t a_size = a->bits & ~PAGE_MASK; 100e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t b_size = b->bits & ~PAGE_MASK; 101e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1020b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans assert((a->bits & CHUNK_MAP_KEY) == CHUNK_MAP_KEY || (a->bits & 1030b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans CHUNK_MAP_DIRTY) == (b->bits & CHUNK_MAP_DIRTY)); 10419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 105e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (a_size > b_size) - (a_size < b_size); 106e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == 0) { 107e476f8a161d445211fd6e54fe370275196e66bcbJason Evans uintptr_t a_mapelm, b_mapelm; 108e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 109e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((a->bits & CHUNK_MAP_KEY) != CHUNK_MAP_KEY) 110e476f8a161d445211fd6e54fe370275196e66bcbJason Evans a_mapelm = (uintptr_t)a; 111e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else { 112e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 113e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Treat keys as though they are lower than anything 114e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * else. 115e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 116e476f8a161d445211fd6e54fe370275196e66bcbJason Evans a_mapelm = 0; 117e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 118e476f8a161d445211fd6e54fe370275196e66bcbJason Evans b_mapelm = (uintptr_t)b; 119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (a_mapelm > b_mapelm) - (a_mapelm < b_mapelm); 121e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 122e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 123e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 125e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 126f3ff75289be32382fa455b4436871e4958fe6bf9Jason Evans/* Generate red-black tree functions. */ 1277372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evansrb_gen(static UNUSED, arena_avail_tree_, arena_avail_tree_t, arena_chunk_map_t, 1287372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans u.rb_link, arena_avail_comp) 129e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 130e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic inline void * 13149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansarena_run_reg_alloc(arena_run_t *run, arena_bin_info_t *bin_info) 132e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 133e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 13484c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans unsigned regind; 13584c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + 13684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans (uintptr_t)bin_info->bitmap_offset); 137e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1381e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans assert(run->nfree > 0); 13984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans assert(bitmap_full(bitmap, &bin_info->bitmap_info) == false); 140e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 14184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans regind = bitmap_sfu(bitmap, &bin_info->bitmap_info); 14284c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans ret = (void *)((uintptr_t)run + (uintptr_t)bin_info->reg0_offset + 143122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans (uintptr_t)(bin_info->reg_interval * regind)); 1441e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans run->nfree--; 14584c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans if (regind == run->nextind) 14684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans run->nextind++; 14784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans assert(regind < run->nextind); 1481e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans return (ret); 1496109fe07a14b7a619365977d9523db9f8b333792Jason Evans} 1506109fe07a14b7a619365977d9523db9f8b333792Jason Evans 1516109fe07a14b7a619365977d9523db9f8b333792Jason Evansstatic inline void 1521e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evansarena_run_reg_dalloc(arena_run_t *run, void *ptr) 1536109fe07a14b7a619365977d9523db9f8b333792Jason Evans{ 15449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 15549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t binind = arena_bin_index(chunk->arena, run->bin); 15649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_bin_info_t *bin_info = &arena_bin_info[binind]; 15784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans unsigned regind = arena_run_regind(run, bin_info, ptr); 15884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + 15984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans (uintptr_t)bin_info->bitmap_offset); 16084c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans 16149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans assert(run->nfree < bin_info->nregs); 1621e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans /* Freeing an interior pointer can cause assertion failure. */ 1631e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans assert(((uintptr_t)ptr - ((uintptr_t)run + 164122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans (uintptr_t)bin_info->reg0_offset)) % 165122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans (uintptr_t)bin_info->reg_interval == 0); 16621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans assert((uintptr_t)ptr >= (uintptr_t)run + 16749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans (uintptr_t)bin_info->reg0_offset); 16884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans /* Freeing an unallocated pointer can cause assertion failure. */ 16984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans assert(bitmap_get(bitmap, &bin_info->bitmap_info, regind)); 170e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 17184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans bitmap_unset(bitmap, &bin_info->bitmap_info, regind); 1721e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans run->nfree++; 173e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 174e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 17521fb95bba6ea922e0523f269c0d9a32640047a29Jason Evansstatic inline void 17621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evansarena_chunk_validate_zeroed(arena_chunk_t *chunk, size_t run_ind) 17721fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans{ 178d4bab21756279db540866998099522dbd39c05f7Jason Evans size_t i; 179ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans UNUSED size_t *p = (size_t *)((uintptr_t)chunk + (run_ind << LG_PAGE)); 180d4bab21756279db540866998099522dbd39c05f7Jason Evans 181ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans for (i = 0; i < PAGE / sizeof(size_t); i++) 18221fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans assert(p[i] == 0); 18321fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans} 18421fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans 185e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 186e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_split(arena_t *arena, arena_run_t *run, size_t size, bool large, 187e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool zero) 188e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 189e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 190bdcadf41e961a3c6bbb37d8d24e4b68a27f2b952Jason Evans size_t run_ind, total_pages, need_pages, rem_pages, i; 19119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans size_t flag_dirty; 19219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_t *runs_avail; 193e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 194e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 195ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans run_ind = (unsigned)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); 1967393f44ff025ca67716fc53b68003fd65122fd97Jason Evans flag_dirty = chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY; 19719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans runs_avail = (flag_dirty != 0) ? &arena->runs_avail_dirty : 19819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans &arena->runs_avail_clean; 1997393f44ff025ca67716fc53b68003fd65122fd97Jason Evans total_pages = (chunk->map[run_ind-map_bias].bits & ~PAGE_MASK) >> 200ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE; 2017393f44ff025ca67716fc53b68003fd65122fd97Jason Evans assert((chunk->map[run_ind+total_pages-1-map_bias].bits & 2027393f44ff025ca67716fc53b68003fd65122fd97Jason Evans CHUNK_MAP_DIRTY) == flag_dirty); 203ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans need_pages = (size >> LG_PAGE); 204e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(need_pages > 0); 205e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(need_pages <= total_pages); 206e476f8a161d445211fd6e54fe370275196e66bcbJason Evans rem_pages = total_pages - need_pages; 207e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2087393f44ff025ca67716fc53b68003fd65122fd97Jason Evans arena_avail_tree_remove(runs_avail, &chunk->map[run_ind-map_bias]); 2097372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 2107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans /* 2117372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans * Update stats_cactive if nactive is crossing a chunk 2127372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans * multiple. 2137372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans */ 2147372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans size_t cactive_diff = CHUNK_CEILING((arena->nactive + 215ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans need_pages) << LG_PAGE) - CHUNK_CEILING(arena->nactive << 216ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE); 2177372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (cactive_diff != 0) 2187372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans stats_cactive_add(cactive_diff); 2197372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 220e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->nactive += need_pages; 221e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 222e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Keep track of trailing unused pages for later use. */ 223e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (rem_pages > 0) { 22419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans if (flag_dirty != 0) { 2257393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+need_pages-map_bias].bits = 226ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (rem_pages << LG_PAGE) | CHUNK_MAP_DIRTY; 2277393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+total_pages-1-map_bias].bits = 228ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (rem_pages << LG_PAGE) | CHUNK_MAP_DIRTY; 22919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } else { 2307393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+need_pages-map_bias].bits = 231ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (rem_pages << LG_PAGE) | 2327393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[run_ind+need_pages-map_bias].bits & 2333377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans CHUNK_MAP_UNZEROED); 2347393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+total_pages-1-map_bias].bits = 235ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (rem_pages << LG_PAGE) | 2367393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[run_ind+total_pages-1-map_bias].bits & 2373377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans CHUNK_MAP_UNZEROED); 23819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } 23919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_insert(runs_avail, 2407393f44ff025ca67716fc53b68003fd65122fd97Jason Evans &chunk->map[run_ind+need_pages-map_bias]); 241e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 242e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 24319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* Update dirty page accounting. */ 24419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans if (flag_dirty != 0) { 24519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans chunk->ndirty -= need_pages; 24619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena->ndirty -= need_pages; 24719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } 24819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 24919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* 25019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * Update the page map separately for large vs. small runs, since it is 25119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * possible to avoid iteration for large mallocs. 25219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans */ 25319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans if (large) { 254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (zero) { 25519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans if (flag_dirty == 0) { 25619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* 25719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * The run is clean, so some pages may be 25819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * zeroed (i.e. never before touched). 25919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans */ 26019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans for (i = 0; i < need_pages; i++) { 2617393f44ff025ca67716fc53b68003fd65122fd97Jason Evans if ((chunk->map[run_ind+i-map_bias].bits 2623377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans & CHUNK_MAP_UNZEROED) != 0) { 263122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans VALGRIND_MAKE_MEM_UNDEFINED( 264122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans (void *)((uintptr_t) 265122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans chunk + ((run_ind+i) << 266122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans LG_PAGE)), PAGE); 26719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans memset((void *)((uintptr_t) 26821fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans chunk + ((run_ind+i) << 269ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE)), 0, PAGE); 2707372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } else if (config_debug) { 271122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans VALGRIND_MAKE_MEM_DEFINED( 272122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans (void *)((uintptr_t) 273122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans chunk + ((run_ind+i) << 274122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans LG_PAGE)), PAGE); 27521fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans arena_chunk_validate_zeroed( 27621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans chunk, run_ind+i); 277940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans } 27819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } 27919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } else { 28019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* 28119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * The run is dirty, so all pages must be 28219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * zeroed. 28319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans */ 284122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans VALGRIND_MAKE_MEM_UNDEFINED((void 285122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans *)((uintptr_t)chunk + (run_ind << 286122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans LG_PAGE)), (need_pages << LG_PAGE)); 28719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans memset((void *)((uintptr_t)chunk + (run_ind << 288ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE)), 0, (need_pages << LG_PAGE)); 289e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 290e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 291e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 292e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 29319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * Set the last element first, in case the run only contains one 29419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * page (i.e. both statements set the same element). 295e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 2967393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+need_pages-1-map_bias].bits = 2977393f44ff025ca67716fc53b68003fd65122fd97Jason Evans CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED | flag_dirty; 298e4f7846f1fd279a039ffa2a41707348187219de4Jason Evans chunk->map[run_ind-map_bias].bits = size | flag_dirty | 299e4f7846f1fd279a039ffa2a41707348187219de4Jason Evans CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 30019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } else { 30119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans assert(zero == false); 30219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* 303940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * Propagate the dirty and unzeroed flags to the allocated 304940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * small run, so that arena_dalloc_bin_run() has the ability to 305940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * conditionally trim clean pages. 30619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans */ 307397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans chunk->map[run_ind-map_bias].bits = 308397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED) | 309397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans CHUNK_MAP_ALLOCATED | flag_dirty; 31021fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans /* 31121fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans * The first page will always be dirtied during small run 31221fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans * initialization, so a validation failure here would not 31321fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans * actually cause an observable failure. 31421fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans */ 3157372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_debug && flag_dirty == 0 && 31621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED) 31721fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans == 0) 31821fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans arena_chunk_validate_zeroed(chunk, run_ind); 31919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans for (i = 1; i < need_pages - 1; i++) { 320ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans chunk->map[run_ind+i-map_bias].bits = (i << LG_PAGE) 321397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans | (chunk->map[run_ind+i-map_bias].bits & 322397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans CHUNK_MAP_UNZEROED) | CHUNK_MAP_ALLOCATED; 3237372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_debug && flag_dirty == 0 && 32421fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans (chunk->map[run_ind+i-map_bias].bits & 32521fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans CHUNK_MAP_UNZEROED) == 0) 32621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans arena_chunk_validate_zeroed(chunk, run_ind+i); 32719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } 328004ed142a66529ecf4a55e8f4fa42ff2e535f586Jason Evans chunk->map[run_ind+need_pages-1-map_bias].bits = ((need_pages 329ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans - 1) << LG_PAGE) | 330397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans (chunk->map[run_ind+need_pages-1-map_bias].bits & 331397e5111b5efd49f61f73c1bad0375c7885a6128Jason Evans CHUNK_MAP_UNZEROED) | CHUNK_MAP_ALLOCATED | flag_dirty; 3327372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_debug && flag_dirty == 0 && 33321fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans (chunk->map[run_ind+need_pages-1-map_bias].bits & 33421fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans CHUNK_MAP_UNZEROED) == 0) { 33521fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans arena_chunk_validate_zeroed(chunk, 33621fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans run_ind+need_pages-1); 33721fb95bba6ea922e0523f269c0d9a32640047a29Jason Evans } 338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 341e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_chunk_t * 342e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_alloc(arena_t *arena) 343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t i; 346e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 347e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (arena->spare != NULL) { 34819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_t *runs_avail; 34919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 350e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = arena->spare; 351e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->spare = NULL; 35219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 35319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* Insert the run into the appropriate runs_avail_* tree. */ 3547393f44ff025ca67716fc53b68003fd65122fd97Jason Evans if ((chunk->map[0].bits & CHUNK_MAP_DIRTY) == 0) 35519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans runs_avail = &arena->runs_avail_clean; 35619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans else 35719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans runs_avail = &arena->runs_avail_dirty; 3588de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans assert((chunk->map[0].bits & ~PAGE_MASK) == arena_maxclass); 3598de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans assert((chunk->map[chunk_npages-1-map_bias].bits & ~PAGE_MASK) 3608de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans == arena_maxclass); 3618de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans assert((chunk->map[0].bits & CHUNK_MAP_DIRTY) == 3628de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans (chunk->map[chunk_npages-1-map_bias].bits & 3638de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans CHUNK_MAP_DIRTY)); 3647393f44ff025ca67716fc53b68003fd65122fd97Jason Evans arena_avail_tree_insert(runs_avail, &chunk->map[0]); 365e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 36641631d00618d7262125e501c91d31b4d70e605faJason Evans bool zero; 3673377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans size_t unzeroed; 36841631d00618d7262125e501c91d31b4d70e605faJason Evans 36941631d00618d7262125e501c91d31b4d70e605faJason Evans zero = false; 370e00572b384c81bd2aba57fac32f7077a34388915Jason Evans malloc_mutex_unlock(&arena->lock); 371eae269036c9f702d9fa9be497a1a2aa1be13a29eMike Hommey chunk = (arena_chunk_t *)chunk_alloc(chunksize, chunksize, 372eae269036c9f702d9fa9be497a1a2aa1be13a29eMike Hommey false, &zero); 373e00572b384c81bd2aba57fac32f7077a34388915Jason Evans malloc_mutex_lock(&arena->lock); 374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (chunk == NULL) 375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 3767372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 3777372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.mapped += chunksize; 378e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 379e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->arena = arena; 3802caa4715ed4f787f263239ff97dd824636289286Jason Evans ql_elm_new(chunk, link_dirty); 381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->dirtied = false; 382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Claim that no pages are in use, since the header is merely 385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * overhead. 386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->ndirty = 0; 388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Initialize the map to contain one maximal free untouched run. 39141631d00618d7262125e501c91d31b4d70e605faJason Evans * Mark the pages as zeroed iff chunk_alloc() returned a zeroed 39241631d00618d7262125e501c91d31b4d70e605faJason Evans * chunk. 393e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 3943377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans unzeroed = zero ? 0 : CHUNK_MAP_UNZEROED; 3953377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans chunk->map[0].bits = arena_maxclass | unzeroed; 3963377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans /* 3973377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans * There is no need to initialize the internal page map entries 3983377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans * unless the chunk is not zeroed. 3993377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans */ 4003377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans if (zero == false) { 4013377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans for (i = map_bias+1; i < chunk_npages-1; i++) 4023377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans chunk->map[i-map_bias].bits = unzeroed; 4037372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } else if (config_debug) { 404940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans for (i = map_bias+1; i < chunk_npages-1; i++) 405940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert(chunk->map[i-map_bias].bits == unzeroed); 406940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans } 407004ed142a66529ecf4a55e8f4fa42ff2e535f586Jason Evans chunk->map[chunk_npages-1-map_bias].bits = arena_maxclass | 408004ed142a66529ecf4a55e8f4fa42ff2e535f586Jason Evans unzeroed; 409e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 41019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* Insert the run into the runs_avail_clean tree. */ 41119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_insert(&arena->runs_avail_clean, 4127393f44ff025ca67716fc53b68003fd65122fd97Jason Evans &chunk->map[0]); 41319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } 414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 415e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (chunk); 416e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 417e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 418e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 419e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk) 420e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 42119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_t *runs_avail; 422e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 4238d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans /* 4248d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans * Remove run from the appropriate runs_avail_* tree, so that the arena 4258d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans * does not use it. 4268d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans */ 4277393f44ff025ca67716fc53b68003fd65122fd97Jason Evans if ((chunk->map[0].bits & CHUNK_MAP_DIRTY) == 0) 4288d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans runs_avail = &arena->runs_avail_clean; 4298d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans else 4308d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans runs_avail = &arena->runs_avail_dirty; 4317393f44ff025ca67716fc53b68003fd65122fd97Jason Evans arena_avail_tree_remove(runs_avail, &chunk->map[0]); 4328d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans 4338d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans if (arena->spare != NULL) { 434e00572b384c81bd2aba57fac32f7077a34388915Jason Evans arena_chunk_t *spare = arena->spare; 435e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 4368d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans arena->spare = chunk; 437e00572b384c81bd2aba57fac32f7077a34388915Jason Evans if (spare->dirtied) { 438e00572b384c81bd2aba57fac32f7077a34388915Jason Evans ql_remove(&chunk->arena->chunks_dirty, spare, 4392caa4715ed4f787f263239ff97dd824636289286Jason Evans link_dirty); 440e00572b384c81bd2aba57fac32f7077a34388915Jason Evans arena->ndirty -= spare->ndirty; 441e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 442e00572b384c81bd2aba57fac32f7077a34388915Jason Evans malloc_mutex_unlock(&arena->lock); 44312a488782681cbd740a5f54e0b7e74ea84858e21Jason Evans chunk_dealloc((void *)spare, chunksize, true); 444e00572b384c81bd2aba57fac32f7077a34388915Jason Evans malloc_mutex_lock(&arena->lock); 4457372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 4467372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.mapped -= chunksize; 4478d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans } else 4488d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans arena->spare = chunk; 449e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 450e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 451e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t * 452e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_alloc(arena_t *arena, size_t size, bool large, bool zero) 453e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 454e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 455e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 456e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_map_t *mapelm, key; 457e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 458e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size <= arena_maxclass); 459e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((size & PAGE_MASK) == 0); 460e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 461e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Search the arena's chunks for the lowest best fit. */ 462e476f8a161d445211fd6e54fe370275196e66bcbJason Evans key.bits = size | CHUNK_MAP_KEY; 46319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans mapelm = arena_avail_tree_nsearch(&arena->runs_avail_dirty, &key); 46419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans if (mapelm != NULL) { 46519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); 4667393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t pageind = (((uintptr_t)mapelm - 4677393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) 4687393f44ff025ca67716fc53b68003fd65122fd97Jason Evans + map_bias; 46919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 47019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << 471ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE)); 47219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_run_split(arena, run, size, large, zero); 47319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans return (run); 47419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } 47519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans mapelm = arena_avail_tree_nsearch(&arena->runs_avail_clean, &key); 476e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (mapelm != NULL) { 477e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); 4787393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t pageind = (((uintptr_t)mapelm - 4797393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) 4807393f44ff025ca67716fc53b68003fd65122fd97Jason Evans + map_bias; 481e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 482e00572b384c81bd2aba57fac32f7077a34388915Jason Evans run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << 483ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE)); 484e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_split(arena, run, size, large, zero); 485e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (run); 486e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 487e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 488e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 489e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * No usable runs. Create a new chunk from which to allocate the run. 490e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 491e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = arena_chunk_alloc(arena); 492e00572b384c81bd2aba57fac32f7077a34388915Jason Evans if (chunk != NULL) { 493ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans run = (arena_run_t *)((uintptr_t)chunk + (map_bias << LG_PAGE)); 494e00572b384c81bd2aba57fac32f7077a34388915Jason Evans arena_run_split(arena, run, size, large, zero); 495e00572b384c81bd2aba57fac32f7077a34388915Jason Evans return (run); 496e00572b384c81bd2aba57fac32f7077a34388915Jason Evans } 497e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 498e00572b384c81bd2aba57fac32f7077a34388915Jason Evans /* 499e00572b384c81bd2aba57fac32f7077a34388915Jason Evans * arena_chunk_alloc() failed, but another thread may have made 500e00572b384c81bd2aba57fac32f7077a34388915Jason Evans * sufficient memory available while this one dropped arena->lock in 501e00572b384c81bd2aba57fac32f7077a34388915Jason Evans * arena_chunk_alloc(), so search one more time. 502e00572b384c81bd2aba57fac32f7077a34388915Jason Evans */ 50319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans mapelm = arena_avail_tree_nsearch(&arena->runs_avail_dirty, &key); 50419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans if (mapelm != NULL) { 50519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); 5067393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t pageind = (((uintptr_t)mapelm - 5077393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) 5087393f44ff025ca67716fc53b68003fd65122fd97Jason Evans + map_bias; 50919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 51019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << 511ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE)); 51219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_run_split(arena, run, size, large, zero); 51319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans return (run); 51419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } 51519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans mapelm = arena_avail_tree_nsearch(&arena->runs_avail_clean, &key); 516e00572b384c81bd2aba57fac32f7077a34388915Jason Evans if (mapelm != NULL) { 517e00572b384c81bd2aba57fac32f7077a34388915Jason Evans arena_chunk_t *run_chunk = CHUNK_ADDR2BASE(mapelm); 5187393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t pageind = (((uintptr_t)mapelm - 5197393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (uintptr_t)run_chunk->map) / sizeof(arena_chunk_map_t)) 5207393f44ff025ca67716fc53b68003fd65122fd97Jason Evans + map_bias; 521e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 522e00572b384c81bd2aba57fac32f7077a34388915Jason Evans run = (arena_run_t *)((uintptr_t)run_chunk + (pageind << 523ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE)); 524e00572b384c81bd2aba57fac32f7077a34388915Jason Evans arena_run_split(arena, run, size, large, zero); 525e00572b384c81bd2aba57fac32f7077a34388915Jason Evans return (run); 526e00572b384c81bd2aba57fac32f7077a34388915Jason Evans } 527e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 528e00572b384c81bd2aba57fac32f7077a34388915Jason Evans return (NULL); 529e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 530e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 53105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evansstatic inline void 53205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evansarena_maybe_purge(arena_t *arena) 53305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans{ 53405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 53505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans /* Enforce opt_lg_dirty_mult. */ 536799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans if (opt_lg_dirty_mult >= 0 && arena->ndirty > arena->npurgatory && 537799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans (arena->ndirty - arena->npurgatory) > chunk_npages && 538799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans (arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty - 539799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans arena->npurgatory)) 5406005f0710cf07d60659d91b20b7ff5592d310027Jason Evans arena_purge(arena, false); 54105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans} 54205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 54305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evansstatic inline void 54405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evansarena_chunk_purge(arena_t *arena, arena_chunk_t *chunk) 54505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans{ 54605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans ql_head(arena_chunk_map_t) mapelms; 54705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans arena_chunk_map_t *mapelm; 5483377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans size_t pageind, flag_unzeroed; 54905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans size_t ndirty; 55005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans size_t nmadvise; 55105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 55205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans ql_new(&mapelms); 55305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 5543377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans flag_unzeroed = 5552dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans#ifdef JEMALLOC_PURGE_MADVISE_DONTNEED 5562dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans /* 5572dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans * madvise(..., MADV_DONTNEED) results in zero-filled pages for anonymous 5582dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans * mappings, but not for file-backed mappings. 5592dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans */ 5604162627757889ea999264c2ddbc3c354768774e2Jason Evans 0 5613377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans#else 5624162627757889ea999264c2ddbc3c354768774e2Jason Evans CHUNK_MAP_UNZEROED 5632dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans#endif 5644162627757889ea999264c2ddbc3c354768774e2Jason Evans ; 565c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans 56605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans /* 56705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans * If chunk is the spare, temporarily re-allocate it, 1) so that its 56819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * run is reinserted into runs_avail_dirty, and 2) so that it cannot be 56905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans * completely discarded by another thread while arena->lock is dropped 57005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans * by this thread. Note that the arena_run_dalloc() call will 57105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans * implicitly deallocate the chunk, so no explicit action is required 57205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans * in this function to deallocate the chunk. 57319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * 57419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * Note that once a chunk contains dirty pages, it cannot again contain 57519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * a single run unless 1) it is a dirty run, or 2) this function purges 57619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * dirty pages and causes the transition to a single clean run. Thus 57719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * (chunk == arena->spare) is possible, but it is not possible for 57819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * this function to be called on the spare unless it contains a dirty 57919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * run. 58005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans */ 58119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans if (chunk == arena->spare) { 5827393f44ff025ca67716fc53b68003fd65122fd97Jason Evans assert((chunk->map[0].bits & CHUNK_MAP_DIRTY) != 0); 58305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans arena_chunk_alloc(arena); 58419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans } 58505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 58619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* Temporarily allocate all free dirty runs within chunk. */ 5877393f44ff025ca67716fc53b68003fd65122fd97Jason Evans for (pageind = map_bias; pageind < chunk_npages;) { 5887393f44ff025ca67716fc53b68003fd65122fd97Jason Evans mapelm = &chunk->map[pageind-map_bias]; 58905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans if ((mapelm->bits & CHUNK_MAP_ALLOCATED) == 0) { 59019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans size_t npages; 59105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 592ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans npages = mapelm->bits >> LG_PAGE; 593e69bee01de62b56d3e585042d341743239568043Jason Evans assert(pageind + npages <= chunk_npages); 59419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans if (mapelm->bits & CHUNK_MAP_DIRTY) { 595c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans size_t i; 596c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans 59719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_remove( 59819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans &arena->runs_avail_dirty, mapelm); 599c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans 600ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans mapelm->bits = (npages << LG_PAGE) | 6018de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans flag_unzeroed | CHUNK_MAP_LARGE | 6028de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans CHUNK_MAP_ALLOCATED; 603c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans /* 604c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans * Update internal elements in the page map, so 6053377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans * that CHUNK_MAP_UNZEROED is properly set. 606c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans */ 607c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans for (i = 1; i < npages - 1; i++) { 6087393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[pageind+i-map_bias].bits = 6093377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans flag_unzeroed; 610c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans } 611c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans if (npages > 1) { 6127393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[ 6137393f44ff025ca67716fc53b68003fd65122fd97Jason Evans pageind+npages-1-map_bias].bits = 6148de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans flag_unzeroed | CHUNK_MAP_LARGE | 6158de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans CHUNK_MAP_ALLOCATED; 616c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans } 617c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans 6187372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 6197372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans /* 6207372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans * Update stats_cactive if nactive is 6217372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans * crossing a chunk multiple. 6227372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans */ 6237372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans size_t cactive_diff = 6247372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans CHUNK_CEILING((arena->nactive + 625ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans npages) << LG_PAGE) - 6267372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans CHUNK_CEILING(arena->nactive << 627ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE); 6287372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (cactive_diff != 0) 6297372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans stats_cactive_add(cactive_diff); 6307372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 63119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena->nactive += npages; 63219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* Append to list for later processing. */ 63319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans ql_elm_new(mapelm, u.ql_link); 63419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans ql_tail_insert(&mapelms, mapelm, u.ql_link); 63505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans } 63619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 63705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans pageind += npages; 63805b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans } else { 63905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans /* Skip allocated run. */ 640c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans if (mapelm->bits & CHUNK_MAP_LARGE) 641ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans pageind += mapelm->bits >> LG_PAGE; 642c03a63d68df9ddbb80f997d8be7bc04e5f3d53ebJason Evans else { 64305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans arena_run_t *run = (arena_run_t *)((uintptr_t) 644ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans chunk + (uintptr_t)(pageind << LG_PAGE)); 645e69bee01de62b56d3e585042d341743239568043Jason Evans 646ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans assert((mapelm->bits >> LG_PAGE) == 0); 64749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t binind = arena_bin_index(arena, 64849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans run->bin); 64949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_bin_info_t *bin_info = 65049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans &arena_bin_info[binind]; 651ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans pageind += bin_info->run_size >> LG_PAGE; 65205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans } 65305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans } 65405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans } 655e69bee01de62b56d3e585042d341743239568043Jason Evans assert(pageind == chunk_npages); 65605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 6577372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_debug) 6587372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans ndirty = chunk->ndirty; 6597372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 6607372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.purged += chunk->ndirty; 66105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans arena->ndirty -= chunk->ndirty; 66205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans chunk->ndirty = 0; 66305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans ql_remove(&arena->chunks_dirty, chunk, link_dirty); 66405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans chunk->dirtied = false; 66505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 66605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans malloc_mutex_unlock(&arena->lock); 6677372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 6687372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans nmadvise = 0; 66905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans ql_foreach(mapelm, &mapelms, u.ql_link) { 6707393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / 6717393f44ff025ca67716fc53b68003fd65122fd97Jason Evans sizeof(arena_chunk_map_t)) + map_bias; 672ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t npages = mapelm->bits >> LG_PAGE; 67305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 674e69bee01de62b56d3e585042d341743239568043Jason Evans assert(pageind + npages <= chunk_npages); 67519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans assert(ndirty >= npages); 6767372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_debug) 6777372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans ndirty -= npages; 6782dbecf1f6267fae7a161b9c39cfd4d04ce168a29Jason Evans 679666c5bf7a8baaa842da69cb402948411432a9d00Mike Hommey pages_purge((void *)((uintptr_t)chunk + (pageind << LG_PAGE)), 680666c5bf7a8baaa842da69cb402948411432a9d00Mike Hommey (npages << LG_PAGE)); 6817372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 6827372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans nmadvise++; 68305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans } 68405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans assert(ndirty == 0); 68505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans malloc_mutex_lock(&arena->lock); 6867372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 6877372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nmadvise += nmadvise; 68805b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 68905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans /* Deallocate runs. */ 69005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans for (mapelm = ql_first(&mapelms); mapelm != NULL; 69105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans mapelm = ql_first(&mapelms)) { 6927393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t pageind = (((uintptr_t)mapelm - (uintptr_t)chunk->map) / 6937393f44ff025ca67716fc53b68003fd65122fd97Jason Evans sizeof(arena_chunk_map_t)) + map_bias; 69405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + 695ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (uintptr_t)(pageind << LG_PAGE)); 69605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 69705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans ql_remove(&mapelms, mapelm, u.ql_link); 69805b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans arena_run_dalloc(arena, run, false); 69905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans } 70005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans} 70105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 702e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 7036005f0710cf07d60659d91b20b7ff5592d310027Jason Evansarena_purge(arena_t *arena, bool all) 704e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 705e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 70605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans size_t npurgatory; 7077372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_debug) { 7087372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans size_t ndirty = 0; 709e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 7107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans ql_foreach(chunk, &arena->chunks_dirty, link_dirty) { 7117372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans assert(chunk->dirtied); 7127372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans ndirty += chunk->ndirty; 7137372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 7147372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans assert(ndirty == arena->ndirty); 7152caa4715ed4f787f263239ff97dd824636289286Jason Evans } 716af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans assert(arena->ndirty > arena->npurgatory || all); 717f9a8edbb50f8cbcaf8ed62b36e8d7191ed223d2aJason Evans assert(arena->ndirty - arena->npurgatory > chunk_npages || all); 718af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans assert((arena->nactive >> opt_lg_dirty_mult) < (arena->ndirty - 719f9a8edbb50f8cbcaf8ed62b36e8d7191ed223d2aJason Evans arena->npurgatory) || all); 720e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 7217372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 7227372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.npurge++; 723e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 724e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 72505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans * Compute the minimum number of pages that this thread should try to 726799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * purge, and add the result to arena->npurgatory. This will keep 727799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * multiple threads from racing to reduce ndirty below the threshold. 728e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 7296005f0710cf07d60659d91b20b7ff5592d310027Jason Evans npurgatory = arena->ndirty - arena->npurgatory; 730af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans if (all == false) { 731af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans assert(npurgatory >= arena->nactive >> opt_lg_dirty_mult); 7326005f0710cf07d60659d91b20b7ff5592d310027Jason Evans npurgatory -= arena->nactive >> opt_lg_dirty_mult; 733af8ad3ec6abe9840bd503535a604a6173ce73515Jason Evans } 734799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans arena->npurgatory += npurgatory; 735799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans 73605b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans while (npurgatory > 0) { 73705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans /* Get next chunk with dirty pages. */ 7382caa4715ed4f787f263239ff97dd824636289286Jason Evans chunk = ql_first(&arena->chunks_dirty); 73905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans if (chunk == NULL) { 74005b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans /* 74105b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans * This thread was unable to purge as many pages as 74205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans * originally intended, due to races with other threads 743799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * that either did some of the purging work, or re-used 744799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * dirty pages. 74505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans */ 746799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans arena->npurgatory -= npurgatory; 747799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans return; 748e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 74905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans while (chunk->ndirty == 0) { 7502caa4715ed4f787f263239ff97dd824636289286Jason Evans ql_remove(&arena->chunks_dirty, chunk, link_dirty); 751e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk->dirtied = false; 75205b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans chunk = ql_first(&arena->chunks_dirty); 75305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans if (chunk == NULL) { 75405b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans /* Same logic as for above. */ 755799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans arena->npurgatory -= npurgatory; 756799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans return; 75705b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans } 758e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 75905b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans 760799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans if (chunk->ndirty > npurgatory) { 761799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans /* 762799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * This thread will, at a minimum, purge all the dirty 763799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * pages in chunk, so set npurgatory to reflect this 764799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * thread's commitment to purge the pages. This tends 765799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * to reduce the chances of the following scenario: 766799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * 767799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * 1) This thread sets arena->npurgatory such that 768799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * (arena->ndirty - arena->npurgatory) is at the 769799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * threshold. 770799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * 2) This thread drops arena->lock. 771799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * 3) Another thread causes one or more pages to be 772799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * dirtied, and immediately determines that it must 773799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * purge dirty pages. 774799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * 775799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * If this scenario *does* play out, that's okay, 776799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * because all of the purging work being done really 777799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans * needs to happen. 778799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans */ 779799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans arena->npurgatory += chunk->ndirty - npurgatory; 780799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans npurgatory = chunk->ndirty; 781799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans } 782799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans 783799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans arena->npurgatory -= chunk->ndirty; 784799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans npurgatory -= chunk->ndirty; 78505b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans arena_chunk_purge(arena, chunk); 786e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 787e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 788e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 7896005f0710cf07d60659d91b20b7ff5592d310027Jason Evansvoid 7906005f0710cf07d60659d91b20b7ff5592d310027Jason Evansarena_purge_all(arena_t *arena) 7916005f0710cf07d60659d91b20b7ff5592d310027Jason Evans{ 7926005f0710cf07d60659d91b20b7ff5592d310027Jason Evans 7936005f0710cf07d60659d91b20b7ff5592d310027Jason Evans malloc_mutex_lock(&arena->lock); 7946005f0710cf07d60659d91b20b7ff5592d310027Jason Evans arena_purge(arena, true); 7956005f0710cf07d60659d91b20b7ff5592d310027Jason Evans malloc_mutex_unlock(&arena->lock); 7966005f0710cf07d60659d91b20b7ff5592d310027Jason Evans} 7976005f0710cf07d60659d91b20b7ff5592d310027Jason Evans 798e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 799e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_dalloc(arena_t *arena, arena_run_t *run, bool dirty) 800e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 801e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 80219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans size_t size, run_ind, run_pages, flag_dirty; 80319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_t *runs_avail; 804e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 805e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 806ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); 8077393f44ff025ca67716fc53b68003fd65122fd97Jason Evans assert(run_ind >= map_bias); 808e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(run_ind < chunk_npages); 8098de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_LARGE) != 0) { 8107393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size = chunk->map[run_ind-map_bias].bits & ~PAGE_MASK; 811ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans assert(size == PAGE || 812ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (chunk->map[run_ind+(size>>LG_PAGE)-1-map_bias].bits & 8138de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans ~PAGE_MASK) == 0); 814ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans assert((chunk->map[run_ind+(size>>LG_PAGE)-1-map_bias].bits & 8158de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans CHUNK_MAP_LARGE) != 0); 816ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans assert((chunk->map[run_ind+(size>>LG_PAGE)-1-map_bias].bits & 8178de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans CHUNK_MAP_ALLOCATED) != 0); 81849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans } else { 81949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t binind = arena_bin_index(arena, run->bin); 82049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_bin_info_t *bin_info = &arena_bin_info[binind]; 82149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size = bin_info->run_size; 82249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans } 823ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans run_pages = (size >> LG_PAGE); 8247372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 8257372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans /* 8267372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans * Update stats_cactive if nactive is crossing a chunk 8277372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans * multiple. 8287372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans */ 829ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t cactive_diff = CHUNK_CEILING(arena->nactive << LG_PAGE) - 830ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans CHUNK_CEILING((arena->nactive - run_pages) << LG_PAGE); 8317372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (cactive_diff != 0) 8327372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans stats_cactive_sub(cactive_diff); 8337372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 834e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->nactive -= run_pages; 835e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 83619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* 83719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * The run is dirty if the caller claims to have dirtied it, as well as 83819b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * if it was already dirty before being allocated. 83919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans */ 8407393f44ff025ca67716fc53b68003fd65122fd97Jason Evans if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) != 0) 84119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans dirty = true; 84219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans flag_dirty = dirty ? CHUNK_MAP_DIRTY : 0; 84319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans runs_avail = dirty ? &arena->runs_avail_dirty : 84419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans &arena->runs_avail_clean; 84519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 846e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Mark pages as unallocated in the chunk map. */ 847e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (dirty) { 848940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[run_ind-map_bias].bits = size | CHUNK_MAP_DIRTY; 8497393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+run_pages-1-map_bias].bits = size | 850940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_DIRTY; 851e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 85219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans chunk->ndirty += run_pages; 85319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena->ndirty += run_pages; 854e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 8557393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind-map_bias].bits = size | 8563377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_UNZEROED); 8577393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+run_pages-1-map_bias].bits = size | 8587393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[run_ind+run_pages-1-map_bias].bits & 8593377ffa1f4f8e67bce1e36624285e5baf5f9ecefJason Evans CHUNK_MAP_UNZEROED); 860e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 861e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 862e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Try to coalesce forward. */ 863e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (run_ind + run_pages < chunk_npages && 8647393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[run_ind+run_pages-map_bias].bits & CHUNK_MAP_ALLOCATED) 8657393f44ff025ca67716fc53b68003fd65122fd97Jason Evans == 0 && (chunk->map[run_ind+run_pages-map_bias].bits & 8667393f44ff025ca67716fc53b68003fd65122fd97Jason Evans CHUNK_MAP_DIRTY) == flag_dirty) { 8677393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t nrun_size = chunk->map[run_ind+run_pages-map_bias].bits & 868e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ~PAGE_MASK; 869ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t nrun_pages = nrun_size >> LG_PAGE; 870e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 871e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 872e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Remove successor from runs_avail; the coalesced run is 873e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * inserted later. 874e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 87512ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits 87612ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans & ~PAGE_MASK) == nrun_size); 87712ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits 87812ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans & CHUNK_MAP_ALLOCATED) == 0); 87912ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans assert((chunk->map[run_ind+run_pages+nrun_pages-1-map_bias].bits 88012ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans & CHUNK_MAP_DIRTY) == flag_dirty); 88119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_remove(runs_avail, 8827393f44ff025ca67716fc53b68003fd65122fd97Jason Evans &chunk->map[run_ind+run_pages-map_bias]); 883e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 884e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size += nrun_size; 88512ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans run_pages += nrun_pages; 886e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 8877393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind-map_bias].bits = size | 8887393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_FLAGS_MASK); 8897393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+run_pages-1-map_bias].bits = size | 8907393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[run_ind+run_pages-1-map_bias].bits & 891e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 892e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 893e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 894e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Try to coalesce backward. */ 8957393f44ff025ca67716fc53b68003fd65122fd97Jason Evans if (run_ind > map_bias && (chunk->map[run_ind-1-map_bias].bits & 8967393f44ff025ca67716fc53b68003fd65122fd97Jason Evans CHUNK_MAP_ALLOCATED) == 0 && (chunk->map[run_ind-1-map_bias].bits & 89719b3d618924b3542a264612f906bc53bbcec8b70Jason Evans CHUNK_MAP_DIRTY) == flag_dirty) { 8987393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t prun_size = chunk->map[run_ind-1-map_bias].bits & 8997393f44ff025ca67716fc53b68003fd65122fd97Jason Evans ~PAGE_MASK; 900ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t prun_pages = prun_size >> LG_PAGE; 901e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 90212ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans run_ind -= prun_pages; 903e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 904e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 905e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Remove predecessor from runs_avail; the coalesced run is 906e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * inserted later. 907e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 90812ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans assert((chunk->map[run_ind-map_bias].bits & ~PAGE_MASK) 90912ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans == prun_size); 91012ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_ALLOCATED) 91112ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans == 0); 91212ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) 91312ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans == flag_dirty); 9147393f44ff025ca67716fc53b68003fd65122fd97Jason Evans arena_avail_tree_remove(runs_avail, 9157393f44ff025ca67716fc53b68003fd65122fd97Jason Evans &chunk->map[run_ind-map_bias]); 916e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 917e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size += prun_size; 91812ca91402bc5d5c5a1cca495957463bb8e71fdcfJason Evans run_pages += prun_pages; 919e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 9207393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind-map_bias].bits = size | 9217393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[run_ind-map_bias].bits & CHUNK_MAP_FLAGS_MASK); 9227393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+run_pages-1-map_bias].bits = size | 9237393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[run_ind+run_pages-1-map_bias].bits & 924e476f8a161d445211fd6e54fe370275196e66bcbJason Evans CHUNK_MAP_FLAGS_MASK); 925e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 926e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 927e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Insert into runs_avail, now that coalescing is complete. */ 9288de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans assert((chunk->map[run_ind-map_bias].bits & ~PAGE_MASK) == 9298de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans (chunk->map[run_ind+run_pages-1-map_bias].bits & ~PAGE_MASK)); 9308de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans assert((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) == 9318de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans (chunk->map[run_ind+run_pages-1-map_bias].bits & CHUNK_MAP_DIRTY)); 9327393f44ff025ca67716fc53b68003fd65122fd97Jason Evans arena_avail_tree_insert(runs_avail, &chunk->map[run_ind-map_bias]); 933e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 9348d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans if (dirty) { 9358d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans /* 9368d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans * Insert into chunks_dirty before potentially calling 9378d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans * arena_chunk_dealloc(), so that chunks_dirty and 9388d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans * arena->ndirty are consistent. 9398d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans */ 9408d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans if (chunk->dirtied == false) { 9418d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans ql_tail_insert(&arena->chunks_dirty, chunk, link_dirty); 9428d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans chunk->dirtied = true; 9438d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans } 9448d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans } 9458d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans 9464fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans /* 9474fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans * Deallocate chunk if it is now completely unused. The bit 9484fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans * manipulation checks whether the first run is unallocated and extends 9494fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans * to the end of the chunk. 9504fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans */ 9517393f44ff025ca67716fc53b68003fd65122fd97Jason Evans if ((chunk->map[0].bits & (~PAGE_MASK | CHUNK_MAP_ALLOCATED)) == 9527393f44ff025ca67716fc53b68003fd65122fd97Jason Evans arena_maxclass) 953e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_dealloc(arena, chunk); 954e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 9554fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans /* 9568d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans * It is okay to do dirty page processing here even if the chunk was 9574fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans * deallocated above, since in that case it is the spare. Waiting 9584fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans * until after possible chunk deallocation to do dirty processing 9594fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans * allows for an old spare to be fully deallocated, thus decreasing the 9604fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans * chances of spuriously crossing the dirty page purging threshold. 9614fb7f513376c0bb73fa1e4e1e89966af9cb2b9ecJason Evans */ 9628d4203c72de878c3976adc5db1e09d7ec0618d63Jason Evans if (dirty) 96305b21be347d66b4afd5147ecd26e8cb22f6ea3feJason Evans arena_maybe_purge(arena); 964e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 965e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 966e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 967e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_trim_head(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 968e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t oldsize, size_t newsize) 969e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 970ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; 971ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t head_npages = (oldsize - newsize) >> LG_PAGE; 972940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans size_t flag_dirty = chunk->map[pageind-map_bias].bits & CHUNK_MAP_DIRTY; 973e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 974e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(oldsize > newsize); 975e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 976e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 977e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Update the chunk map so that arena_run_dalloc() can treat the 978940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * leading run as separately allocated. Set the last element of each 979940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * run first, in case of single-page runs. 980e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 981940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_LARGE) != 0); 982940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_ALLOCATED) != 0); 983940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind+head_npages-1-map_bias].bits = flag_dirty | 984940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans (chunk->map[pageind+head_npages-1-map_bias].bits & 985940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 986940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind-map_bias].bits = (oldsize - newsize) 987940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans | flag_dirty | (chunk->map[pageind-map_bias].bits & 988940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 989940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans 9907372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_debug) { 991ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans UNUSED size_t tail_npages = newsize >> LG_PAGE; 992940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias] 993940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans .bits & ~PAGE_MASK) == 0); 994940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias] 995940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans .bits & CHUNK_MAP_DIRTY) == flag_dirty); 996940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias] 997940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans .bits & CHUNK_MAP_LARGE) != 0); 998940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias] 999940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans .bits & CHUNK_MAP_ALLOCATED) != 0); 1000940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans } 1001940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind+head_npages-map_bias].bits = newsize | flag_dirty | 1002940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans (chunk->map[pageind+head_npages-map_bias].bits & 1003940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_FLAGS_MASK) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 1004e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1005e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_dalloc(arena, run, false); 1006e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1007e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1008e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 1009e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_run_trim_tail(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 1010e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t oldsize, size_t newsize, bool dirty) 1011e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1012ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; 1013ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t head_npages = newsize >> LG_PAGE; 1014ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t tail_npages = (oldsize - newsize) >> LG_PAGE; 1015940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans size_t flag_dirty = chunk->map[pageind-map_bias].bits & 1016940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_DIRTY; 1017e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1018e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(oldsize > newsize); 1019e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1020e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1021e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Update the chunk map so that arena_run_dalloc() can treat the 1022940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * trailing run as separately allocated. Set the last element of each 1023940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * run first, in case of single-page runs. 1024e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1025940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_LARGE) != 0); 1026940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind-map_bias].bits & CHUNK_MAP_ALLOCATED) != 0); 1027940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind+head_npages-1-map_bias].bits = flag_dirty | 1028940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans (chunk->map[pageind+head_npages-1-map_bias].bits & 1029940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 1030940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind-map_bias].bits = newsize | flag_dirty | 1031940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans (chunk->map[pageind-map_bias].bits & CHUNK_MAP_UNZEROED) | 1032940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 1033940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans 1034940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits & 1035940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans ~PAGE_MASK) == 0); 1036940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits & 1037940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_LARGE) != 0); 1038940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans assert((chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits & 1039940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_ALLOCATED) != 0); 1040940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits = 1041940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans flag_dirty | 1042940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans (chunk->map[pageind+head_npages+tail_npages-1-map_bias].bits & 1043940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 1044940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind+head_npages-map_bias].bits = (oldsize - newsize) | 1045940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans flag_dirty | (chunk->map[pageind+head_npages-map_bias].bits & 1046940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_UNZEROED) | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 1047e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1048e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_dalloc(arena, (arena_run_t *)((uintptr_t)run + newsize), 1049e476f8a161d445211fd6e54fe370275196e66bcbJason Evans dirty); 1050e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1051e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1052e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic arena_run_t * 1053e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_runs_first(arena_bin_t *bin) 1054e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1055e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_chunk_map_t *mapelm = arena_run_tree_first(&bin->runs); 1056e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (mapelm != NULL) { 1057e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 1058e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t pageind; 1059e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1060e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(mapelm); 10617393f44ff025ca67716fc53b68003fd65122fd97Jason Evans pageind = ((((uintptr_t)mapelm - (uintptr_t)chunk->map) / 10627393f44ff025ca67716fc53b68003fd65122fd97Jason Evans sizeof(arena_chunk_map_t))) + map_bias; 1063e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_run_t *run = (arena_run_t *)((uintptr_t)chunk + 1064ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (uintptr_t)((pageind - (mapelm->bits >> LG_PAGE)) << 1065ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans LG_PAGE)); 1066e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans return (run); 1067e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans } 1068e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1069e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans return (NULL); 1070e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans} 1071e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1072e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic void 1073e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_runs_insert(arena_bin_t *bin, arena_run_t *run) 1074e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans{ 1075e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_chunk_t *chunk = CHUNK_ADDR2BASE(run); 1076ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; 1077e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_chunk_map_t *mapelm = &chunk->map[pageind-map_bias]; 1078e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1079e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans assert(arena_run_tree_search(&bin->runs, mapelm) == NULL); 1080e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1081e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_run_tree_insert(&bin->runs, mapelm); 1082e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans} 1083e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1084e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic void 1085e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_runs_remove(arena_bin_t *bin, arena_run_t *run) 1086e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans{ 1087e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_chunk_t *chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 1088ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t pageind = ((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE; 1089e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_chunk_map_t *mapelm = &chunk->map[pageind-map_bias]; 1090e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1091e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans assert(arena_run_tree_search(&bin->runs, mapelm) != NULL); 1092e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1093e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_run_tree_remove(&bin->runs, mapelm); 1094e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans} 1095e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1096e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic arena_run_t * 1097e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_nonfull_run_tryget(arena_bin_t *bin) 1098e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans{ 1099e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_run_t *run = arena_bin_runs_first(bin); 1100e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans if (run != NULL) { 1101e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_bin_runs_remove(bin, run); 11027372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 11037372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.reruns++; 1104e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1105e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans return (run); 1106e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans} 1107e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1108e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansstatic arena_run_t * 1109e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evansarena_bin_nonfull_run_get(arena_t *arena, arena_bin_t *bin) 1110e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans{ 1111e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_run_t *run; 1112e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans size_t binind; 1113e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_bin_info_t *bin_info; 1114e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans 1115e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans /* Look for a usable run. */ 1116e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans run = arena_bin_nonfull_run_tryget(bin); 1117e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans if (run != NULL) 1118e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans return (run); 1119e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* No existing runs have any space available. */ 1120e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 112149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans binind = arena_bin_index(arena, bin); 112249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans bin_info = &arena_bin_info[binind]; 112349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 1124e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Allocate a new run. */ 1125e00572b384c81bd2aba57fac32f7077a34388915Jason Evans malloc_mutex_unlock(&bin->lock); 1126e69bee01de62b56d3e585042d341743239568043Jason Evans /******************************/ 112786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_lock(&arena->lock); 112849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans run = arena_run_alloc(arena, bin_info->run_size, false, false); 1129e00572b384c81bd2aba57fac32f7077a34388915Jason Evans if (run != NULL) { 113084c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans bitmap_t *bitmap = (bitmap_t *)((uintptr_t)run + 113184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans (uintptr_t)bin_info->bitmap_offset); 113284c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans 1133e00572b384c81bd2aba57fac32f7077a34388915Jason Evans /* Initialize run internals. */ 1134f54166e7ef5313c3b5c773cbb0ca2af95f5a15aeJason Evans VALGRIND_MAKE_MEM_UNDEFINED(run, bin_info->reg0_offset - 1135f54166e7ef5313c3b5c773cbb0ca2af95f5a15aeJason Evans bin_info->redzone_size); 1136e00572b384c81bd2aba57fac32f7077a34388915Jason Evans run->bin = bin; 113784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans run->nextind = 0; 113849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans run->nfree = bin_info->nregs; 113984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans bitmap_init(bitmap, &bin_info->bitmap_info); 1140e69bee01de62b56d3e585042d341743239568043Jason Evans } 1141e69bee01de62b56d3e585042d341743239568043Jason Evans malloc_mutex_unlock(&arena->lock); 1142e69bee01de62b56d3e585042d341743239568043Jason Evans /********************************/ 1143e69bee01de62b56d3e585042d341743239568043Jason Evans malloc_mutex_lock(&bin->lock); 1144e69bee01de62b56d3e585042d341743239568043Jason Evans if (run != NULL) { 11457372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 11467372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.nruns++; 11477372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.curruns++; 11487372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 1149e00572b384c81bd2aba57fac32f7077a34388915Jason Evans return (run); 1150e00572b384c81bd2aba57fac32f7077a34388915Jason Evans } 1151e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 1152e00572b384c81bd2aba57fac32f7077a34388915Jason Evans /* 1153e00572b384c81bd2aba57fac32f7077a34388915Jason Evans * arena_run_alloc() failed, but another thread may have made 1154940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * sufficient memory available while this one dropped bin->lock above, 1155e00572b384c81bd2aba57fac32f7077a34388915Jason Evans * so search one more time. 1156e00572b384c81bd2aba57fac32f7077a34388915Jason Evans */ 1157e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans run = arena_bin_nonfull_run_tryget(bin); 1158e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans if (run != NULL) 1159e00572b384c81bd2aba57fac32f7077a34388915Jason Evans return (run); 1160e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 1161e00572b384c81bd2aba57fac32f7077a34388915Jason Evans return (NULL); 1162e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1163e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 11641e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans/* Re-fill bin->runcur, then call arena_run_reg_alloc(). */ 1165e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void * 1166e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_bin_malloc_hard(arena_t *arena, arena_bin_t *bin) 1167e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1168e00572b384c81bd2aba57fac32f7077a34388915Jason Evans void *ret; 116949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t binind; 117049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_bin_info_t *bin_info; 1171e00572b384c81bd2aba57fac32f7077a34388915Jason Evans arena_run_t *run; 1172e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 117349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans binind = arena_bin_index(arena, bin); 117449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans bin_info = &arena_bin_info[binind]; 1175e00572b384c81bd2aba57fac32f7077a34388915Jason Evans bin->runcur = NULL; 1176e00572b384c81bd2aba57fac32f7077a34388915Jason Evans run = arena_bin_nonfull_run_get(arena, bin); 1177e00572b384c81bd2aba57fac32f7077a34388915Jason Evans if (bin->runcur != NULL && bin->runcur->nfree > 0) { 1178e00572b384c81bd2aba57fac32f7077a34388915Jason Evans /* 1179e00572b384c81bd2aba57fac32f7077a34388915Jason Evans * Another thread updated runcur while this one ran without the 1180e00572b384c81bd2aba57fac32f7077a34388915Jason Evans * bin lock in arena_bin_nonfull_run_get(). 1181e00572b384c81bd2aba57fac32f7077a34388915Jason Evans */ 1182e00572b384c81bd2aba57fac32f7077a34388915Jason Evans assert(bin->runcur->nfree > 0); 118349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans ret = arena_run_reg_alloc(bin->runcur, bin_info); 1184e00572b384c81bd2aba57fac32f7077a34388915Jason Evans if (run != NULL) { 1185940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans arena_chunk_t *chunk; 1186940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans 1187940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans /* 1188940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * arena_run_alloc() may have allocated run, or it may 118984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans * have pulled run from the bin's run tree. Therefore 1190940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * it is unsafe to make any assumptions about how run 1191940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * has previously been used, and arena_bin_lower_run() 1192940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * must be called, as if a region were just deallocated 1193940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * from the run. 1194940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans */ 1195940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 119649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans if (run->nfree == bin_info->nregs) 11978de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans arena_dalloc_bin_run(arena, chunk, run, bin); 11988de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans else 11998de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans arena_bin_lower_run(arena, chunk, run, bin); 1200e00572b384c81bd2aba57fac32f7077a34388915Jason Evans } 1201e00572b384c81bd2aba57fac32f7077a34388915Jason Evans return (ret); 1202e00572b384c81bd2aba57fac32f7077a34388915Jason Evans } 1203e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 1204e00572b384c81bd2aba57fac32f7077a34388915Jason Evans if (run == NULL) 1205e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1206e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 1207e00572b384c81bd2aba57fac32f7077a34388915Jason Evans bin->runcur = run; 1208e00572b384c81bd2aba57fac32f7077a34388915Jason Evans 1209e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(bin->runcur->nfree > 0); 1210e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 121149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans return (arena_run_reg_alloc(bin->runcur, bin_info)); 1212e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1213e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 121486815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evansvoid 121586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evansarena_prof_accum(arena_t *arena, uint64_t accumbytes) 121686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans{ 121786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans 121878f7352259768f670f8e1f9b000388dd32b62493Jason Evans cassert(config_prof); 121978f7352259768f670f8e1f9b000388dd32b62493Jason Evans 122078f7352259768f670f8e1f9b000388dd32b62493Jason Evans if (config_prof && prof_interval != 0) { 122186815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans arena->prof_accumbytes += accumbytes; 122286815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans if (arena->prof_accumbytes >= prof_interval) { 122386815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans prof_idump(); 122486815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans arena->prof_accumbytes -= prof_interval; 122586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans } 122686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans } 122786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans} 122886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans 1229e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid 12307372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evansarena_tcache_fill_small(arena_t *arena, tcache_bin_t *tbin, size_t binind, 12317372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans uint64_t prof_accumbytes) 1232e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1233e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned i, nfill; 1234e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin; 1235e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 1236e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ptr; 1237e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1238e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(tbin->ncached == 0); 1239e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 12407372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_prof) { 12417372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans malloc_mutex_lock(&arena->lock); 12427372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena_prof_accum(arena, prof_accumbytes); 12437372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans malloc_mutex_unlock(&arena->lock); 12447372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 1245e69bee01de62b56d3e585042d341743239568043Jason Evans bin = &arena->bins[binind]; 1246e69bee01de62b56d3e585042d341743239568043Jason Evans malloc_mutex_lock(&bin->lock); 12471dcb4f86b23a5760f5a717ace716360b63b33fadJason Evans for (i = 0, nfill = (tcache_bin_info[binind].ncached_max >> 12481dcb4f86b23a5760f5a717ace716360b63b33fadJason Evans tbin->lg_fill_div); i < nfill; i++) { 1249e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((run = bin->runcur) != NULL && run->nfree > 0) 125049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans ptr = arena_run_reg_alloc(run, &arena_bin_info[binind]); 1251e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else 1252e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ptr = arena_bin_malloc_hard(arena, bin); 12533fa9a2fad83a3014d5069b5a2530a0cfb8d8d197Jason Evans if (ptr == NULL) 1254e476f8a161d445211fd6e54fe370275196e66bcbJason Evans break; 1255122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if (config_fill && opt_junk) { 1256122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans arena_alloc_junk_small(ptr, &arena_bin_info[binind], 1257122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans true); 1258122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 12599c43c13a35220c10d97a886616899189daceb359Jason Evans /* Insert such that low regions get used first. */ 12609c43c13a35220c10d97a886616899189daceb359Jason Evans tbin->avail[nfill - 1 - i] = ptr; 1261e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 12627372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 12637372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.allocated += i * arena_bin_info[binind].reg_size; 12647372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.nmalloc += i; 12657372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.nrequests += tbin->tstats.nrequests; 12667372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.nfills++; 12677372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans tbin->tstats.nrequests = 0; 12687372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 126986815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_unlock(&bin->lock); 1270e476f8a161d445211fd6e54fe370275196e66bcbJason Evans tbin->ncached = i; 1271e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1272e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1273122449b073bcbaa504c4f592ea2d733503c272d2Jason Evansvoid 1274122449b073bcbaa504c4f592ea2d733503c272d2Jason Evansarena_alloc_junk_small(void *ptr, arena_bin_info_t *bin_info, bool zero) 1275122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans{ 1276122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans 1277122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if (zero) { 1278122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans size_t redzone_size = bin_info->redzone_size; 1279122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans memset((void *)((uintptr_t)ptr - redzone_size), 0xa5, 1280122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans redzone_size); 1281122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans memset((void *)((uintptr_t)ptr + bin_info->reg_size), 0xa5, 1282122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans redzone_size); 1283122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } else { 1284122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans memset((void *)((uintptr_t)ptr - bin_info->redzone_size), 0xa5, 1285122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg_interval); 1286122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 1287122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans} 1288122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans 1289122449b073bcbaa504c4f592ea2d733503c272d2Jason Evansvoid 1290122449b073bcbaa504c4f592ea2d733503c272d2Jason Evansarena_dalloc_junk_small(void *ptr, arena_bin_info_t *bin_info) 1291122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans{ 1292122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans size_t size = bin_info->reg_size; 1293122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans size_t redzone_size = bin_info->redzone_size; 1294122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans size_t i; 1295122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bool error = false; 1296122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans 1297122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans for (i = 1; i <= redzone_size; i++) { 1298122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans unsigned byte; 1299122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if ((byte = *(uint8_t *)((uintptr_t)ptr - i)) != 0xa5) { 1300122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans error = true; 1301122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans malloc_printf("<jemalloc>: Corrupt redzone " 1302122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans "%zu byte%s before %p (size %zu), byte=%#x\n", i, 1303122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans (i == 1) ? "" : "s", ptr, size, byte); 1304122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 1305122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 1306122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans for (i = 0; i < redzone_size; i++) { 1307122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans unsigned byte; 1308122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if ((byte = *(uint8_t *)((uintptr_t)ptr + size + i)) != 0xa5) { 1309122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans error = true; 1310122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans malloc_printf("<jemalloc>: Corrupt redzone " 1311122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans "%zu byte%s after end of %p (size %zu), byte=%#x\n", 1312122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans i, (i == 1) ? "" : "s", ptr, size, byte); 1313122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 1314122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 1315122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if (opt_abort && error) 1316122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans abort(); 1317122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans 1318122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans memset((void *)((uintptr_t)ptr - redzone_size), 0x5a, 1319122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg_interval); 1320122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans} 1321122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans 1322e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 1323e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_small(arena_t *arena, size_t size, bool zero) 1324e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1325e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 1326e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin; 1327e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_t *run; 1328e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t binind; 1329e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 133041ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans binind = SMALL_SIZE2BIN(size); 1331b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans assert(binind < NBINS); 1332e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[binind]; 133349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size = arena_bin_info[binind].reg_size; 1334e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 133586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_lock(&bin->lock); 1336e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if ((run = bin->runcur) != NULL && run->nfree > 0) 133749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans ret = arena_run_reg_alloc(run, &arena_bin_info[binind]); 1338e476f8a161d445211fd6e54fe370275196e66bcbJason Evans else 1339e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = arena_bin_malloc_hard(arena, bin); 1340e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1341e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == NULL) { 134286815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_unlock(&bin->lock); 1343e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1344e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1345e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 13467372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 13477372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.allocated += size; 13487372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.nmalloc++; 13497372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.nrequests++; 13507372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 135186815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_unlock(&bin->lock); 13527372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_prof && isthreaded == false) { 135386815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_lock(&arena->lock); 1354d34f9e7e9306698e298a703c28526cd6bfc073ecJason Evans arena_prof_accum(arena, size); 135586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_unlock(&arena->lock); 135686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans } 1357e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1358e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (zero == false) { 13597372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill) { 1360122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if (opt_junk) { 1361122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans arena_alloc_junk_small(ret, 1362122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans &arena_bin_info[binind], false); 1363122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } else if (opt_zero) 13647372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans memset(ret, 0, size); 13657372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 1366122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } else { 1367122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if (config_fill && opt_junk) { 1368122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans arena_alloc_junk_small(ret, &arena_bin_info[binind], 1369122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans true); 1370122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 1371122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans VALGRIND_MAKE_MEM_UNDEFINED(ret, size); 1372e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ret, 0, size); 1373122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 1374e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1375e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1376e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1377e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1378e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 1379e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_malloc_large(arena_t *arena, size_t size, bool zero) 1380e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1381e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 1382e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1383e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Large allocation. */ 1384e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size = PAGE_CEILING(size); 1385e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1386e476f8a161d445211fd6e54fe370275196e66bcbJason Evans ret = (void *)arena_run_alloc(arena, size, true, zero); 1387e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (ret == NULL) { 1388e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1389e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1390e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 13917372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 13927372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nmalloc_large++; 13937372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nrequests_large++; 13947372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.allocated_large += size; 1395ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; 1396ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; 1397ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; 1398e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 13997372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_prof) 14007372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena_prof_accum(arena, size); 1401e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1402e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1403e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (zero == false) { 14047372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill) { 14057372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (opt_junk) 14067372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans memset(ret, 0xa5, size); 14077372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans else if (opt_zero) 14087372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans memset(ret, 0, size); 14097372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 1410e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1411e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1412e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1413e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1414e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1415e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* Only handles large allocations that require more than page alignment. */ 1416e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 14175ff709c264e52651de25b788692c62ff1f6f389cJason Evansarena_palloc(arena_t *arena, size_t size, size_t alignment, bool zero) 1418e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1419e476f8a161d445211fd6e54fe370275196e66bcbJason Evans void *ret; 14205ff709c264e52651de25b788692c62ff1f6f389cJason Evans size_t alloc_size, leadsize, trailsize; 14215ff709c264e52651de25b788692c62ff1f6f389cJason Evans arena_run_t *run; 1422e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 1423e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1424e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert((size & PAGE_MASK) == 0); 142593443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans 142693443689a4367cc6fe3de1c9e918adc13d8f9100Jason Evans alignment = PAGE_CEILING(alignment); 14275ff709c264e52651de25b788692c62ff1f6f389cJason Evans alloc_size = size + alignment - PAGE; 1428e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1429e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 14305ff709c264e52651de25b788692c62ff1f6f389cJason Evans run = arena_run_alloc(arena, alloc_size, true, zero); 14315ff709c264e52651de25b788692c62ff1f6f389cJason Evans if (run == NULL) { 1432e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1433e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (NULL); 1434e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 14355ff709c264e52651de25b788692c62ff1f6f389cJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(run); 1436e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 14375ff709c264e52651de25b788692c62ff1f6f389cJason Evans leadsize = ALIGNMENT_CEILING((uintptr_t)run, alignment) - 14385ff709c264e52651de25b788692c62ff1f6f389cJason Evans (uintptr_t)run; 14395ff709c264e52651de25b788692c62ff1f6f389cJason Evans assert(alloc_size >= leadsize + size); 14405ff709c264e52651de25b788692c62ff1f6f389cJason Evans trailsize = alloc_size - leadsize - size; 14415ff709c264e52651de25b788692c62ff1f6f389cJason Evans ret = (void *)((uintptr_t)run + leadsize); 14425ff709c264e52651de25b788692c62ff1f6f389cJason Evans if (leadsize != 0) { 14435ff709c264e52651de25b788692c62ff1f6f389cJason Evans arena_run_trim_head(arena, chunk, run, alloc_size, alloc_size - 14445ff709c264e52651de25b788692c62ff1f6f389cJason Evans leadsize); 14455ff709c264e52651de25b788692c62ff1f6f389cJason Evans } 14465ff709c264e52651de25b788692c62ff1f6f389cJason Evans if (trailsize != 0) { 14475ff709c264e52651de25b788692c62ff1f6f389cJason Evans arena_run_trim_tail(arena, chunk, ret, size + trailsize, size, 14485ff709c264e52651de25b788692c62ff1f6f389cJason Evans false); 1449e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1450e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 14517372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 14527372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nmalloc_large++; 14537372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nrequests_large++; 14547372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.allocated_large += size; 1455ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; 1456ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; 1457ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; 1458e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1459e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1460e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 14617372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill && zero == false) { 14628e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans if (opt_junk) 14638e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans memset(ret, 0xa5, size); 14648e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans else if (opt_zero) 14658e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans memset(ret, 0, size); 14668e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans } 1467e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1468e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1469e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 14700b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evansvoid 14710b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evansarena_prof_promoted(const void *ptr, size_t size) 14720b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans{ 14730b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans arena_chunk_t *chunk; 14740b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans size_t pageind, binind; 14750b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans 147678f7352259768f670f8e1f9b000388dd32b62493Jason Evans cassert(config_prof); 14770b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans assert(ptr != NULL); 14780b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans assert(CHUNK_ADDR2BASE(ptr) != ptr); 1479122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans assert(isalloc(ptr, false) == PAGE); 1480122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans assert(isalloc(ptr, true) == PAGE); 1481b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans assert(size <= SMALL_MAXCLASS); 14820b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans 14830b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 1484ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; 148541ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans binind = SMALL_SIZE2BIN(size); 1486b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans assert(binind < NBINS); 14877393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[pageind-map_bias].bits = (chunk->map[pageind-map_bias].bits & 1488e4f7846f1fd279a039ffa2a41707348187219de4Jason Evans ~CHUNK_MAP_CLASS_MASK) | ((binind+1) << CHUNK_MAP_CLASS_SHIFT); 14890b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans 1490122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans assert(isalloc(ptr, false) == PAGE); 1491122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans assert(isalloc(ptr, true) == size); 14920b270a991dd7822b7c7e13d9219f235a5dde9fdfJason Evans} 14936109fe07a14b7a619365977d9523db9f8b333792Jason Evans 1494e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 1495088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evansarena_dissociate_bin_run(arena_chunk_t *chunk, arena_run_t *run, 1496e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin) 1497e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1498e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 149919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* Dissociate run from bin. */ 1500e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (run == bin->runcur) 1501e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = NULL; 150249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans else { 150349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t binind = arena_bin_index(chunk->arena, bin); 150449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_bin_info_t *bin_info = &arena_bin_info[binind]; 150549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 150649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans if (bin_info->nregs != 1) { 150749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* 150849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * This block's conditional is necessary because if the 150949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * run only contains one region, then it never gets 151049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * inserted into the non-full runs tree. 151149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans */ 1512e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_bin_runs_remove(bin, run); 151349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans } 1514e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1515088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans} 1516088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans 1517088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evansstatic void 1518088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evansarena_dalloc_bin_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 1519088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans arena_bin_t *bin) 1520088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans{ 152149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t binind; 152249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_bin_info_t *bin_info; 1523088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans size_t npages, run_ind, past; 1524088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans 1525088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans assert(run != bin->runcur); 1526088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans assert(arena_run_tree_search(&bin->runs, &chunk->map[ 1527ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (((uintptr_t)run-(uintptr_t)chunk)>>LG_PAGE)-map_bias]) == NULL); 152886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans 152949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans binind = arena_bin_index(chunk->arena, run->bin); 153049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans bin_info = &arena_bin_info[binind]; 153149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 1532e00572b384c81bd2aba57fac32f7077a34388915Jason Evans malloc_mutex_unlock(&bin->lock); 1533e00572b384c81bd2aba57fac32f7077a34388915Jason Evans /******************************/ 1534ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans npages = bin_info->run_size >> LG_PAGE; 1535ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans run_ind = (size_t)(((uintptr_t)run - (uintptr_t)chunk) >> LG_PAGE); 153684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans past = (size_t)(PAGE_CEILING((uintptr_t)run + 153784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans (uintptr_t)bin_info->reg0_offset + (uintptr_t)(run->nextind * 1538122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg_interval - bin_info->redzone_size) - 1539122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans (uintptr_t)chunk) >> LG_PAGE); 154086815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_lock(&arena->lock); 154119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans 154219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* 154319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * If the run was originally clean, and some pages were never touched, 154419b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * trim the clean pages before deallocating the dirty portion of the 154519b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * run. 154619b3d618924b3542a264612f906bc53bbcec8b70Jason Evans */ 15477393f44ff025ca67716fc53b68003fd65122fd97Jason Evans if ((chunk->map[run_ind-map_bias].bits & CHUNK_MAP_DIRTY) == 0 && past 15487393f44ff025ca67716fc53b68003fd65122fd97Jason Evans - run_ind < npages) { 154919b3d618924b3542a264612f906bc53bbcec8b70Jason Evans /* 155019b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * Trim clean pages. Convert to large run beforehand. Set the 155119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans * last map element first, in case this is a one-page run. 155219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans */ 15537393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[run_ind+npages-1-map_bias].bits = CHUNK_MAP_LARGE | 1554940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans (chunk->map[run_ind+npages-1-map_bias].bits & 1555940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_FLAGS_MASK); 155649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans chunk->map[run_ind-map_bias].bits = bin_info->run_size | 15577393f44ff025ca67716fc53b68003fd65122fd97Jason Evans CHUNK_MAP_LARGE | (chunk->map[run_ind-map_bias].bits & 15587393f44ff025ca67716fc53b68003fd65122fd97Jason Evans CHUNK_MAP_FLAGS_MASK); 1559ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena_run_trim_tail(arena, chunk, run, (npages << LG_PAGE), 1560ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans ((past - run_ind) << LG_PAGE), false); 1561940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans /* npages = past - run_ind; */ 15621e0a636c11e694b4b157f40198fd463fcfc6c57aJason Evans } 156319b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_run_dalloc(arena, run, true); 156486815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_unlock(&arena->lock); 1565e00572b384c81bd2aba57fac32f7077a34388915Jason Evans /****************************/ 1566e00572b384c81bd2aba57fac32f7077a34388915Jason Evans malloc_mutex_lock(&bin->lock); 15677372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 15687372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.curruns--; 1569e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1570e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1571940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansstatic void 1572940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansarena_bin_lower_run(arena_t *arena, arena_chunk_t *chunk, arena_run_t *run, 1573940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans arena_bin_t *bin) 1574e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1575e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 15768de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans /* 1577e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans * Make sure that if bin->runcur is non-NULL, it refers to the lowest 1578e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans * non-full run. It is okay to NULL runcur out rather than proactively 1579e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans * keeping it pointing at the lowest non-full run. 15808de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans */ 1581e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans if ((uintptr_t)run < (uintptr_t)bin->runcur) { 15828de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans /* Switch runcur. */ 1583e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans if (bin->runcur->nfree > 0) 1584e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_bin_runs_insert(bin, bin->runcur); 15858de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans bin->runcur = run; 1586e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans if (config_stats) 1587e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans bin->stats.reruns++; 1588e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans } else 1589e7a1058aaa6b2cbdd19da297bf2250f86dcdac89Jason Evans arena_bin_runs_insert(bin, run); 1590940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans} 1591940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans 1592940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansvoid 1593940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evansarena_dalloc_bin(arena_t *arena, arena_chunk_t *chunk, void *ptr, 1594940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans arena_chunk_map_t *mapelm) 1595940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans{ 1596940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans size_t pageind; 1597940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans arena_run_t *run; 1598940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans arena_bin_t *bin; 1599940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans size_t size; 1600940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans 1601ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; 1602940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans run = (arena_run_t *)((uintptr_t)chunk + (uintptr_t)((pageind - 1603ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (mapelm->bits >> LG_PAGE)) << LG_PAGE)); 1604940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans bin = run->bin; 160549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t binind = arena_bin_index(arena, bin); 160649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_bin_info_t *bin_info = &arena_bin_info[binind]; 16077372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill || config_stats) 16087372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans size = bin_info->reg_size; 1609940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans 16107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill && opt_junk) 1611122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans arena_dalloc_junk_small(ptr, bin_info); 1612940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans 1613940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans arena_run_reg_dalloc(run, ptr); 161449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans if (run->nfree == bin_info->nregs) { 1615088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans arena_dissociate_bin_run(chunk, run, bin); 16168de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans arena_dalloc_bin_run(arena, chunk, run, bin); 1617088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans } else if (run->nfree == 1 && run != bin->runcur) 16188de6a0282333ca742fb2870b1e859968d3c1b11fJason Evans arena_bin_lower_run(arena, chunk, run, bin); 1619e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 16207372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 16217372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.allocated -= size; 16227372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bin->stats.ndalloc++; 16237372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 1624e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1625e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1626e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid 1627b34e8684ec025aa780997c11f847c19fb269755bJason Evansarena_stats_merge(arena_t *arena, size_t *nactive, size_t *ndirty, 1628b34e8684ec025aa780997c11f847c19fb269755bJason Evans arena_stats_t *astats, malloc_bin_stats_t *bstats, 1629b34e8684ec025aa780997c11f847c19fb269755bJason Evans malloc_large_stats_t *lstats) 1630b34e8684ec025aa780997c11f847c19fb269755bJason Evans{ 16313c2343518c2b1fbbd66065c75a3c19f908de1d78Jason Evans unsigned i; 1632b34e8684ec025aa780997c11f847c19fb269755bJason Evans 163386815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_lock(&arena->lock); 1634b34e8684ec025aa780997c11f847c19fb269755bJason Evans *nactive += arena->nactive; 1635b34e8684ec025aa780997c11f847c19fb269755bJason Evans *ndirty += arena->ndirty; 1636b34e8684ec025aa780997c11f847c19fb269755bJason Evans 16374201af05425b69ee37ffca437aca0cdd604d1e51Jason Evans astats->mapped += arena->stats.mapped; 1638b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->npurge += arena->stats.npurge; 1639b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->nmadvise += arena->stats.nmadvise; 1640b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->purged += arena->stats.purged; 1641b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->allocated_large += arena->stats.allocated_large; 1642b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->nmalloc_large += arena->stats.nmalloc_large; 1643b34e8684ec025aa780997c11f847c19fb269755bJason Evans astats->ndalloc_large += arena->stats.ndalloc_large; 1644dafde14e08ddfda747aabb2045b350848b601b2eJason Evans astats->nrequests_large += arena->stats.nrequests_large; 1645b34e8684ec025aa780997c11f847c19fb269755bJason Evans 16463c2343518c2b1fbbd66065c75a3c19f908de1d78Jason Evans for (i = 0; i < nlclasses; i++) { 1647dafde14e08ddfda747aabb2045b350848b601b2eJason Evans lstats[i].nmalloc += arena->stats.lstats[i].nmalloc; 1648dafde14e08ddfda747aabb2045b350848b601b2eJason Evans lstats[i].ndalloc += arena->stats.lstats[i].ndalloc; 1649b34e8684ec025aa780997c11f847c19fb269755bJason Evans lstats[i].nrequests += arena->stats.lstats[i].nrequests; 1650b34e8684ec025aa780997c11f847c19fb269755bJason Evans lstats[i].curruns += arena->stats.lstats[i].curruns; 1651b34e8684ec025aa780997c11f847c19fb269755bJason Evans } 165286815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_unlock(&arena->lock); 165386815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans 1654b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans for (i = 0; i < NBINS; i++) { 165586815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans arena_bin_t *bin = &arena->bins[i]; 165686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans 165786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_lock(&bin->lock); 165886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans bstats[i].allocated += bin->stats.allocated; 165986815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans bstats[i].nmalloc += bin->stats.nmalloc; 166086815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans bstats[i].ndalloc += bin->stats.ndalloc; 166186815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans bstats[i].nrequests += bin->stats.nrequests; 16627372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_tcache) { 16637372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bstats[i].nfills += bin->stats.nfills; 16647372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans bstats[i].nflushes += bin->stats.nflushes; 16657372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 166686815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans bstats[i].nruns += bin->stats.nruns; 166786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans bstats[i].reruns += bin->stats.reruns; 166886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans bstats[i].curruns += bin->stats.curruns; 166986815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans malloc_mutex_unlock(&bin->lock); 167086815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans } 1671b34e8684ec025aa780997c11f847c19fb269755bJason Evans} 1672e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1673e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid 1674e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_dalloc_large(arena_t *arena, arena_chunk_t *chunk, void *ptr) 1675e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 167613668262d17fb5950e2441bc9d56a15db9c93877Jason Evans 16777372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill || config_stats) { 1678ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; 16797393f44ff025ca67716fc53b68003fd65122fd97Jason Evans size_t size = chunk->map[pageind-map_bias].bits & ~PAGE_MASK; 1680e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 16817372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill && config_stats && opt_junk) 1682e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset(ptr, 0x5a, size); 16837372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 16847372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.ndalloc_large++; 16857372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.allocated_large -= size; 1686ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].ndalloc++; 1687ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].curruns--; 16887372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 1689e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1690e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1691e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_dalloc(arena, (arena_run_t *)ptr, true); 1692e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1693e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1694e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic void 1695e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large_shrink(arena_t *arena, arena_chunk_t *chunk, void *ptr, 16968e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans size_t oldsize, size_t size) 1697e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1698e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1699e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size < oldsize); 1700e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1701e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1702e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Shrink the run, and make trailing pages available for other 1703e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * allocations. 1704e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1705e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 1706e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_trim_tail(arena, chunk, (arena_run_t *)ptr, oldsize, size, 1707e476f8a161d445211fd6e54fe370275196e66bcbJason Evans true); 17087372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 17097372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.ndalloc_large++; 17107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.allocated_large -= oldsize; 1711ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(oldsize >> LG_PAGE) - 1].ndalloc++; 1712ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(oldsize >> LG_PAGE) - 1].curruns--; 17137372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans 17147372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nmalloc_large++; 17157372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nrequests_large++; 17167372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.allocated_large += size; 1717ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; 1718ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].nrequests++; 1719ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; 1720e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1721e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1722e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1723e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1724e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool 1725e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_ralloc_large_grow(arena_t *arena, arena_chunk_t *chunk, void *ptr, 17268e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans size_t oldsize, size_t size, size_t extra, bool zero) 1727e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1728ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t pageind = ((uintptr_t)ptr - (uintptr_t)chunk) >> LG_PAGE; 1729ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t npages = oldsize >> LG_PAGE; 17308e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans size_t followsize; 1731e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 17327393f44ff025ca67716fc53b68003fd65122fd97Jason Evans assert(oldsize == (chunk->map[pageind-map_bias].bits & ~PAGE_MASK)); 1733e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1734e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Try to extend the run. */ 17358e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans assert(size + extra > oldsize); 1736e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_lock(&arena->lock); 17377393f44ff025ca67716fc53b68003fd65122fd97Jason Evans if (pageind + npages < chunk_npages && 17387393f44ff025ca67716fc53b68003fd65122fd97Jason Evans (chunk->map[pageind+npages-map_bias].bits 17398e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans & CHUNK_MAP_ALLOCATED) == 0 && (followsize = 17407393f44ff025ca67716fc53b68003fd65122fd97Jason Evans chunk->map[pageind+npages-map_bias].bits & ~PAGE_MASK) >= size - 17417393f44ff025ca67716fc53b68003fd65122fd97Jason Evans oldsize) { 1742e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 1743e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * The next run is available and sufficiently large. Split the 1744e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * following run, then merge the first part with the existing 1745e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * allocation. 1746e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1747940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans size_t flag_dirty; 17488e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans size_t splitsize = (oldsize + followsize <= size + extra) 17498e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans ? followsize : size + extra - oldsize; 1750e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_split(arena, (arena_run_t *)((uintptr_t)chunk + 1751ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans ((pageind+npages) << LG_PAGE)), splitsize, true, zero); 1752e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1753088e6a0a37e197c8db16e3d4c518a5eb762e7657Jason Evans size = oldsize + splitsize; 1754ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans npages = size >> LG_PAGE; 1755e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1756940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans /* 1757940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * Mark the extended run as dirty if either portion of the run 1758940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * was dirty before allocation. This is rather pedantic, 1759940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * because there's not actually any sequence of events that 1760940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * could cause the resulting run to be passed to 1761940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * arena_run_dalloc() with the dirty argument set to false 1762940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans * (which is when dirty flag consistency would really matter). 1763940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans */ 1764940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans flag_dirty = (chunk->map[pageind-map_bias].bits & 1765940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_DIRTY) | 1766940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans (chunk->map[pageind+npages-1-map_bias].bits & 1767940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_DIRTY); 1768940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind-map_bias].bits = size | flag_dirty 1769940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans | CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 1770940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans chunk->map[pageind+npages-1-map_bias].bits = flag_dirty | 1771940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans CHUNK_MAP_LARGE | CHUNK_MAP_ALLOCATED; 1772990d10cefb4b2ff4458086aedba8fc70975a9adcJason Evans 17737372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 17747372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.ndalloc_large++; 17757372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.allocated_large -= oldsize; 1776ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(oldsize >> LG_PAGE) 17777372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans - 1].ndalloc++; 1778ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(oldsize >> LG_PAGE) 17797372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans - 1].curruns--; 17807372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans 17817372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nmalloc_large++; 17827372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.nrequests_large++; 17837372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.allocated_large += size; 1784ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].nmalloc++; 1785ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) 17867372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans - 1].nrequests++; 1787ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena->stats.lstats[(size >> LG_PAGE) - 1].curruns++; 1788940a2e02b27b264cc92e8ecbf186a711ce05ad04Jason Evans } 1789e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1790e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 1791e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1792e476f8a161d445211fd6e54fe370275196e66bcbJason Evans malloc_mutex_unlock(&arena->lock); 1793e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1794e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (true); 1795e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1796e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1797e476f8a161d445211fd6e54fe370275196e66bcbJason Evans/* 1798e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Try to resize a large allocation, in order to avoid copying. This will 1799e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * always fail if growing an object, and the following run is already in use. 1800e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 1801e476f8a161d445211fd6e54fe370275196e66bcbJason Evansstatic bool 18028e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansarena_ralloc_large(void *ptr, size_t oldsize, size_t size, size_t extra, 18038e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans bool zero) 1804e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1805e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size_t psize; 1806e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 18078e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans psize = PAGE_CEILING(size + extra); 1808e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (psize == oldsize) { 1809e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Same size class. */ 18107372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill && opt_junk && size < oldsize) { 1811e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)ptr + size), 0x5a, oldsize - 1812e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size); 1813e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1814e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 1815e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1816e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_chunk_t *chunk; 1817e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_t *arena; 1818e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1819e476f8a161d445211fd6e54fe370275196e66bcbJason Evans chunk = (arena_chunk_t *)CHUNK_ADDR2BASE(ptr); 1820e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena = chunk->arena; 1821e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1822e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (psize < oldsize) { 1823e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Fill before shrinking in order avoid a race. */ 18247372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill && opt_junk) { 1825e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)ptr + size), 0x5a, 1826e476f8a161d445211fd6e54fe370275196e66bcbJason Evans oldsize - size); 1827e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 18288e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans arena_ralloc_large_shrink(arena, chunk, ptr, oldsize, 18298e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans psize); 1830e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 1831e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1832e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bool ret = arena_ralloc_large_grow(arena, chunk, ptr, 18338e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans oldsize, PAGE_CEILING(size), 18348e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans psize - PAGE_CEILING(size), zero); 18357372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill && ret == false && zero == false && 18367372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans opt_zero) { 1837e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memset((void *)((uintptr_t)ptr + oldsize), 0, 1838e476f8a161d445211fd6e54fe370275196e66bcbJason Evans size - oldsize); 1839e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1840e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1841e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1842e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1843e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1844e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1845e476f8a161d445211fd6e54fe370275196e66bcbJason Evansvoid * 18468e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansarena_ralloc_no_move(void *ptr, size_t oldsize, size_t size, size_t extra, 18478e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans bool zero) 1848e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1849e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 18508e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans /* 18518e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans * Avoid moving the allocation if the size class can be left the same. 18528e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans */ 1853e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (oldsize <= arena_maxclass) { 1854b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans if (oldsize <= SMALL_MAXCLASS) { 185549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans assert(arena_bin_info[SMALL_SIZE2BIN(oldsize)].reg_size 185649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans == oldsize); 1857b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans if ((size + extra <= SMALL_MAXCLASS && 185841ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans SMALL_SIZE2BIN(size + extra) == 185941ade967c29ea9312c0b7390ee43bc0c63373f39Jason Evans SMALL_SIZE2BIN(oldsize)) || (size <= oldsize && 18608e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans size + extra >= oldsize)) { 18617372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_fill && opt_junk && size < oldsize) { 18628e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans memset((void *)((uintptr_t)ptr + size), 18638e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans 0x5a, oldsize - size); 18648e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans } 18658e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans return (ptr); 18668e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans } 1867e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } else { 1868e476f8a161d445211fd6e54fe370275196e66bcbJason Evans assert(size <= arena_maxclass); 1869b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans if (size + extra > SMALL_MAXCLASS) { 18708e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans if (arena_ralloc_large(ptr, oldsize, size, 18718e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans extra, zero) == false) 1872e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ptr); 1873e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1874e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1875e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1876e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 18778e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans /* Reallocation would require a move. */ 18788e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans return (NULL); 18798e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans} 18808e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans 18818e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansvoid * 18828e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evansarena_ralloc(void *ptr, size_t oldsize, size_t size, size_t extra, 188301b3fe55ff3ac8e4aa689f09fcb0729da8037638Jason Evans size_t alignment, bool zero, bool try_tcache) 18848e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans{ 18858e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans void *ret; 18868e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans size_t copysize; 18878e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans 18888e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans /* Try to avoid moving the allocation. */ 18898e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans ret = arena_ralloc_no_move(ptr, oldsize, size, extra, zero); 18908e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans if (ret != NULL) 18918e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans return (ret); 18928e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans 1893e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 18948e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans * size and oldsize are different enough that we need to move the 18958e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans * object. In that case, fall back to allocating new space and 18968e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans * copying. 1897e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 189838d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans if (alignment != 0) { 18995ff709c264e52651de25b788692c62ff1f6f389cJason Evans size_t usize = sa2u(size + extra, alignment); 190038d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans if (usize == 0) 190138d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans return (NULL); 190238d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans ret = ipalloc(usize, alignment, zero); 190338d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans } else 190401b3fe55ff3ac8e4aa689f09fcb0729da8037638Jason Evans ret = arena_malloc(NULL, size + extra, zero, try_tcache); 1905e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 19068e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans if (ret == NULL) { 19078e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans if (extra == 0) 19088e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans return (NULL); 19098e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans /* Try again, this time without extra. */ 191038d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans if (alignment != 0) { 19115ff709c264e52651de25b788692c62ff1f6f389cJason Evans size_t usize = sa2u(size, alignment); 191238d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans if (usize == 0) 191338d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans return (NULL); 191438d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans ret = ipalloc(usize, alignment, zero); 191538d9210c464c4ad49655a4da6bc84ea4fbec83d2Jason Evans } else 191601b3fe55ff3ac8e4aa689f09fcb0729da8037638Jason Evans ret = arena_malloc(NULL, size, zero, try_tcache); 19178e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans 19188e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans if (ret == NULL) 19198e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans return (NULL); 19208e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans } 19218e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans 19228e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans /* Junk/zero-filling were already done by ipalloc()/arena_malloc(). */ 19238e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans 19248e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans /* 19258e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans * Copy at most size bytes (not size+extra), since the caller has no 19268e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans * expectation that the extra bytes will be reliably preserved. 19278e3c3c61b5bb676a705450708e7e79698cdc9e0cJason Evans */ 1928e476f8a161d445211fd6e54fe370275196e66bcbJason Evans copysize = (size < oldsize) ? size : oldsize; 1929f54166e7ef5313c3b5c773cbb0ca2af95f5a15aeJason Evans VALGRIND_MAKE_MEM_UNDEFINED(ret, copysize); 1930e476f8a161d445211fd6e54fe370275196e66bcbJason Evans memcpy(ret, ptr, copysize); 1931122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans iqalloc(ptr); 1932e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (ret); 1933e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1934e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1935e476f8a161d445211fd6e54fe370275196e66bcbJason Evansbool 1936e476f8a161d445211fd6e54fe370275196e66bcbJason Evansarena_new(arena_t *arena, unsigned ind) 1937e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 1938e476f8a161d445211fd6e54fe370275196e66bcbJason Evans unsigned i; 1939e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_bin_t *bin; 1940e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 19416109fe07a14b7a619365977d9523db9f8b333792Jason Evans arena->ind = ind; 1942597632be188d2bcc135dad2145cc46ef44897aadJason Evans arena->nthreads = 0; 19436109fe07a14b7a619365977d9523db9f8b333792Jason Evans 1944e476f8a161d445211fd6e54fe370275196e66bcbJason Evans if (malloc_mutex_init(&arena->lock)) 1945e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (true); 1946e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 19477372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) { 19487372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans memset(&arena->stats, 0, sizeof(arena_stats_t)); 19497372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->stats.lstats = 19507372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans (malloc_large_stats_t *)base_alloc(nlclasses * 19517372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans sizeof(malloc_large_stats_t)); 19527372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (arena->stats.lstats == NULL) 19537372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans return (true); 19547372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans memset(arena->stats.lstats, 0, nlclasses * 19557372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans sizeof(malloc_large_stats_t)); 19567372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_tcache) 19577372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans ql_new(&arena->tcache_ql); 19587372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans } 1959e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 19607372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_prof) 19617372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans arena->prof_accumbytes = 0; 1962d34f9e7e9306698e298a703c28526cd6bfc073ecJason Evans 1963e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Initialize chunks. */ 19642caa4715ed4f787f263239ff97dd824636289286Jason Evans ql_new(&arena->chunks_dirty); 1965e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->spare = NULL; 1966e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1967e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->nactive = 0; 1968e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena->ndirty = 0; 1969799ca0b68dd2a87eb7696b7a83ed85378cc6721cJason Evans arena->npurgatory = 0; 1970e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 197119b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_new(&arena->runs_avail_clean); 197219b3d618924b3542a264612f906bc53bbcec8b70Jason Evans arena_avail_tree_new(&arena->runs_avail_dirty); 1973e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1974e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* Initialize bins. */ 1975b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans for (i = 0; i < NBINS; i++) { 1976e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin = &arena->bins[i]; 197786815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans if (malloc_mutex_init(&bin->lock)) 197886815df9dc7d2418a21c87b3dc9747ab42dea73dJason Evans return (true); 1979e476f8a161d445211fd6e54fe370275196e66bcbJason Evans bin->runcur = NULL; 1980e476f8a161d445211fd6e54fe370275196e66bcbJason Evans arena_run_tree_new(&bin->runs); 19817372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_stats) 19827372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans memset(&bin->stats, 0, sizeof(malloc_bin_stats_t)); 1983e476f8a161d445211fd6e54fe370275196e66bcbJason Evans } 1984e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 1985e476f8a161d445211fd6e54fe370275196e66bcbJason Evans return (false); 1986e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 1987e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 198849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans/* 198949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * Calculate bin_info->run_size such that it meets the following constraints: 199049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * 199149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * *) bin_info->run_size >= min_run_size 199249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * *) bin_info->run_size <= arena_maxclass 199349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * *) run header overhead <= RUN_MAX_OVRHD (or header overhead relaxed). 199447e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans * *) bin_info->nregs <= RUN_MAXREGS 199549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * 199684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans * bin_info->nregs, bin_info->bitmap_offset, and bin_info->reg0_offset are also 199784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans * calculated here, since these settings are all interdependent. 199849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans */ 199949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansstatic size_t 200049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansbin_info_run_size_calc(arena_bin_info_t *bin_info, size_t min_run_size) 200149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans{ 2002122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans size_t pad_size; 200349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans size_t try_run_size, good_run_size; 200449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans uint32_t try_nregs, good_nregs; 200549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans uint32_t try_hdr_size, good_hdr_size; 200684c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans uint32_t try_bitmap_offset, good_bitmap_offset; 200749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans uint32_t try_ctx0_offset, good_ctx0_offset; 2008122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans uint32_t try_redzone0_offset, good_redzone0_offset; 200949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 2010ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans assert(min_run_size >= PAGE); 201149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans assert(min_run_size <= arena_maxclass); 201249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 201349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* 2014122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans * Determine redzone size based on minimum alignment and minimum 2015122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans * redzone size. Add padding to the end of the run if it is needed to 2016122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans * align the regions. The padding allows each redzone to be half the 2017122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans * minimum alignment; without the padding, each redzone would have to 2018122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans * be twice as large in order to maintain alignment. 2019122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans */ 2020122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if (config_fill && opt_redzone) { 2021122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans size_t align_min = ZU(1) << (ffs(bin_info->reg_size) - 1); 2022122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans if (align_min <= REDZONE_MINSIZE) { 2023122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->redzone_size = REDZONE_MINSIZE; 2024122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans pad_size = 0; 2025122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } else { 2026122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->redzone_size = align_min >> 1; 2027122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans pad_size = bin_info->redzone_size; 2028122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 2029122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } else { 2030122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->redzone_size = 0; 2031122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans pad_size = 0; 2032122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } 2033122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg_interval = bin_info->reg_size + 2034122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans (bin_info->redzone_size << 1); 2035122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans 2036122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans /* 203749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * Calculate known-valid settings before entering the run_size 203849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * expansion loop, so that the first part of the loop always copies 203949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * valid settings. 204049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * 204149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * The do..while loop iteratively reduces the number of regions until 204249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * the run header and the regions no longer overlap. A closed formula 204349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * would be quite messy, since there is an interdependency between the 204449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * header's mask length and the number of regions. 204549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans */ 204649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_run_size = min_run_size; 2047122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans try_nregs = ((try_run_size - sizeof(arena_run_t)) / 2048122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg_interval) 204949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans + 1; /* Counter-act try_nregs-- in loop. */ 205047e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans if (try_nregs > RUN_MAXREGS) { 205147e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans try_nregs = RUN_MAXREGS 205247e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans + 1; /* Counter-act try_nregs-- in loop. */ 205347e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans } 205449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans do { 205549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_nregs--; 205649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_hdr_size = sizeof(arena_run_t); 205784c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans /* Pad to a long boundary. */ 205884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans try_hdr_size = LONG_CEILING(try_hdr_size); 205984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans try_bitmap_offset = try_hdr_size; 206084c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans /* Add space for bitmap. */ 206184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans try_hdr_size += bitmap_size(try_nregs); 20627372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_prof && opt_prof && prof_promote == false) { 206349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* Pad to a quantum boundary. */ 206449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_hdr_size = QUANTUM_CEILING(try_hdr_size); 206549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_ctx0_offset = try_hdr_size; 206649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* Add space for one (prof_ctx_t *) per region. */ 206749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_hdr_size += try_nregs * sizeof(prof_ctx_t *); 206849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans } else 206949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_ctx0_offset = 0; 2070122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans try_redzone0_offset = try_run_size - (try_nregs * 2071122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg_interval) - pad_size; 2072122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } while (try_hdr_size > try_redzone0_offset); 207349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 207449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* run_size expansion loop. */ 207549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans do { 207649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* 207749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * Copy valid settings before trying more aggressive settings. 207849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans */ 207949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans good_run_size = try_run_size; 208049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans good_nregs = try_nregs; 208149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans good_hdr_size = try_hdr_size; 208284c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans good_bitmap_offset = try_bitmap_offset; 208349f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans good_ctx0_offset = try_ctx0_offset; 2084122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans good_redzone0_offset = try_redzone0_offset; 208549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 208649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* Try more aggressive settings. */ 2087ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans try_run_size += PAGE; 2088122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans try_nregs = ((try_run_size - sizeof(arena_run_t) - pad_size) / 2089122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg_interval) 209049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans + 1; /* Counter-act try_nregs-- in loop. */ 209147e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans if (try_nregs > RUN_MAXREGS) { 209247e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans try_nregs = RUN_MAXREGS 209347e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans + 1; /* Counter-act try_nregs-- in loop. */ 209447e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans } 209549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans do { 209649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_nregs--; 209749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_hdr_size = sizeof(arena_run_t); 209884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans /* Pad to a long boundary. */ 209984c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans try_hdr_size = LONG_CEILING(try_hdr_size); 210084c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans try_bitmap_offset = try_hdr_size; 210184c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans /* Add space for bitmap. */ 210284c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans try_hdr_size += bitmap_size(try_nregs); 21037372b15a31c63ac5cb9ed8aeabc2a0a3c005e8bfJason Evans if (config_prof && opt_prof && prof_promote == false) { 210449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* Pad to a quantum boundary. */ 210549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_hdr_size = QUANTUM_CEILING(try_hdr_size); 210649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_ctx0_offset = try_hdr_size; 210749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* 210849f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans * Add space for one (prof_ctx_t *) per region. 210949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans */ 211049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans try_hdr_size += try_nregs * 211149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans sizeof(prof_ctx_t *); 211249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans } 2113122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans try_redzone0_offset = try_run_size - (try_nregs * 2114122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg_interval) - pad_size; 2115122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans } while (try_hdr_size > try_redzone0_offset); 211649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans } while (try_run_size <= arena_maxclass 211749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans && try_run_size <= arena_maxclass 2118122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans && RUN_MAX_OVRHD * (bin_info->reg_interval << 3) > 2119122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans RUN_MAX_OVRHD_RELAX 2120122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans && (try_redzone0_offset << RUN_BFP) > RUN_MAX_OVRHD * try_run_size 212147e57f9bdadfaf999c9dea5d126edf3a4f1b2995Jason Evans && try_nregs < RUN_MAXREGS); 212249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 2123122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans assert(good_hdr_size <= good_redzone0_offset); 212449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 212549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans /* Copy final settings. */ 212649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans bin_info->run_size = good_run_size; 212749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans bin_info->nregs = good_nregs; 212884c8eefeffa246607790ad12e28b0f6a24ecc59dJason Evans bin_info->bitmap_offset = good_bitmap_offset; 212949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans bin_info->ctx0_offset = good_ctx0_offset; 2130122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans bin_info->reg0_offset = good_redzone0_offset + bin_info->redzone_size; 2131122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans 2132122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans assert(bin_info->reg0_offset - bin_info->redzone_size + (bin_info->nregs 2133122449b073bcbaa504c4f592ea2d733503c272d2Jason Evans * bin_info->reg_interval) + pad_size == bin_info->run_size); 213449f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 213549f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans return (good_run_size); 213649f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans} 213749f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 2138b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansstatic void 213949f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evansbin_info_init(void) 214049f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans{ 214149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans arena_bin_info_t *bin_info; 2142ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans size_t prev_run_size = PAGE; 2143b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans 2144b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#define SIZE_CLASS(bin, delta, size) \ 2145b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans bin_info = &arena_bin_info[bin]; \ 2146b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans bin_info->reg_size = size; \ 2147b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans prev_run_size = bin_info_run_size_calc(bin_info, prev_run_size);\ 2148b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans bitmap_info_init(&bin_info->bitmap_info, bin_info->nregs); 2149b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans SIZE_CLASSES 2150b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans#undef SIZE_CLASS 215149f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans} 215249f7e8f35ac63d0dd526cf68791dc0ca29538ac9Jason Evans 2153b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evansvoid 2154a0bf242230be117a3e54a7d1fc3f11e5a83606ecJason Evansarena_boot(void) 2155e476f8a161d445211fd6e54fe370275196e66bcbJason Evans{ 2156a0bf242230be117a3e54a7d1fc3f11e5a83606ecJason Evans size_t header_size; 21577393f44ff025ca67716fc53b68003fd65122fd97Jason Evans unsigned i; 2158e476f8a161d445211fd6e54fe370275196e66bcbJason Evans 2159e476f8a161d445211fd6e54fe370275196e66bcbJason Evans /* 2160e476f8a161d445211fd6e54fe370275196e66bcbJason Evans * Compute the header size such that it is large enough to contain the 21617393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * page map. The page map is biased to omit entries for the header 21627393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * itself, so some iteration is necessary to compute the map bias. 21637393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * 21647393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * 1) Compute safe header_size and map_bias values that include enough 21657393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * space for an unbiased page map. 21667393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * 2) Refine map_bias based on (1) to omit the header pages in the page 21677393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * map. The resulting map_bias may be one too small. 21687393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * 3) Refine map_bias based on (2). The result will be >= the result 21697393f44ff025ca67716fc53b68003fd65122fd97Jason Evans * from (2), and will always be correct. 2170e476f8a161d445211fd6e54fe370275196e66bcbJason Evans */ 21717393f44ff025ca67716fc53b68003fd65122fd97Jason Evans map_bias = 0; 21727393f44ff025ca67716fc53b68003fd65122fd97Jason Evans for (i = 0; i < 3; i++) { 2173ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans header_size = offsetof(arena_chunk_t, map) + 2174ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans (sizeof(arena_chunk_map_t) * (chunk_npages-map_bias)); 2175ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans map_bias = (header_size >> LG_PAGE) + ((header_size & PAGE_MASK) 2176ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans != 0); 21777393f44ff025ca67716fc53b68003fd65122fd97Jason Evans } 21787393f44ff025ca67716fc53b68003fd65122fd97Jason Evans assert(map_bias > 0); 21797393f44ff025ca67716fc53b68003fd65122fd97Jason Evans 2180ae4c7b4b4092906c641d69b4bf9fcb4a7d50790dJason Evans arena_maxclass = chunksize - (map_bias << LG_PAGE); 2181a0bf242230be117a3e54a7d1fc3f11e5a83606ecJason Evans 2182b172610317babc7f365584ddd7fdaf4eb8d9d04cJason Evans bin_info_init(); 2183e476f8a161d445211fd6e54fe370275196e66bcbJason Evans} 21844e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans 21854e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansvoid 21864e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansarena_prefork(arena_t *arena) 21874e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans{ 21884e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans unsigned i; 21894e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans 21904e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans malloc_mutex_prefork(&arena->lock); 21914e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans for (i = 0; i < NBINS; i++) 21924e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans malloc_mutex_prefork(&arena->bins[i].lock); 21934e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans} 21944e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans 21954e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansvoid 21964e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansarena_postfork_parent(arena_t *arena) 21974e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans{ 21984e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans unsigned i; 21994e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans 22004e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans for (i = 0; i < NBINS; i++) 22014e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans malloc_mutex_postfork_parent(&arena->bins[i].lock); 22024e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans malloc_mutex_postfork_parent(&arena->lock); 22034e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans} 22044e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans 22054e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansvoid 22064e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evansarena_postfork_child(arena_t *arena) 22074e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans{ 22084e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans unsigned i; 22094e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans 22104e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans for (i = 0; i < NBINS; i++) 22114e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans malloc_mutex_postfork_child(&arena->bins[i].lock); 22124e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans malloc_mutex_postfork_child(&arena->lock); 22134e2e3dd9cf19ed5991938a708a8b50611aa5bbf8Jason Evans} 2214