1a4bd5210SJason Evans #define JEMALLOC_CTL_C_ 2a4bd5210SJason Evans #include "jemalloc/internal/jemalloc_internal.h" 3a4bd5210SJason Evans 4a4bd5210SJason Evans /******************************************************************************/ 5a4bd5210SJason Evans /* Data. */ 6a4bd5210SJason Evans 7a4bd5210SJason Evans /* 8a4bd5210SJason Evans * ctl_mtx protects the following: 9a4bd5210SJason Evans * - ctl_stats.* 10a4bd5210SJason Evans * - opt_prof_active 11a4bd5210SJason Evans */ 12a4bd5210SJason Evans static malloc_mutex_t ctl_mtx; 13a4bd5210SJason Evans static bool ctl_initialized; 14a4bd5210SJason Evans static uint64_t ctl_epoch; 15a4bd5210SJason Evans static ctl_stats_t ctl_stats; 16a4bd5210SJason Evans 17a4bd5210SJason Evans /******************************************************************************/ 18a4bd5210SJason Evans /* Function prototypes for non-inline static functions. */ 19a4bd5210SJason Evans 20a4bd5210SJason Evans #define CTL_PROTO(n) \ 21a4bd5210SJason Evans static int n##_ctl(const size_t *mib, size_t miblen, void *oldp, \ 22a4bd5210SJason Evans size_t *oldlenp, void *newp, size_t newlen); 23a4bd5210SJason Evans 24a4bd5210SJason Evans #define INDEX_PROTO(n) \ 25a4bd5210SJason Evans const ctl_node_t *n##_index(const size_t *mib, size_t miblen, \ 26a4bd5210SJason Evans size_t i); 27a4bd5210SJason Evans 28a4bd5210SJason Evans static bool ctl_arena_init(ctl_arena_stats_t *astats); 29a4bd5210SJason Evans static void ctl_arena_clear(ctl_arena_stats_t *astats); 30a4bd5210SJason Evans static void ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, 31a4bd5210SJason Evans arena_t *arena); 32a4bd5210SJason Evans static void ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, 33a4bd5210SJason Evans ctl_arena_stats_t *astats); 34a4bd5210SJason Evans static void ctl_arena_refresh(arena_t *arena, unsigned i); 35a4bd5210SJason Evans static void ctl_refresh(void); 36a4bd5210SJason Evans static bool ctl_init(void); 37a4bd5210SJason Evans static int ctl_lookup(const char *name, ctl_node_t const **nodesp, 38a4bd5210SJason Evans size_t *mibp, size_t *depthp); 39a4bd5210SJason Evans 40a4bd5210SJason Evans CTL_PROTO(version) 41a4bd5210SJason Evans CTL_PROTO(epoch) 42a4bd5210SJason Evans CTL_PROTO(thread_tcache_enabled) 43a4bd5210SJason Evans CTL_PROTO(thread_tcache_flush) 44a4bd5210SJason Evans CTL_PROTO(thread_arena) 45a4bd5210SJason Evans CTL_PROTO(thread_allocated) 46a4bd5210SJason Evans CTL_PROTO(thread_allocatedp) 47a4bd5210SJason Evans CTL_PROTO(thread_deallocated) 48a4bd5210SJason Evans CTL_PROTO(thread_deallocatedp) 49a4bd5210SJason Evans CTL_PROTO(config_debug) 50a4bd5210SJason Evans CTL_PROTO(config_dss) 51a4bd5210SJason Evans CTL_PROTO(config_fill) 52a4bd5210SJason Evans CTL_PROTO(config_lazy_lock) 53a4bd5210SJason Evans CTL_PROTO(config_munmap) 54a4bd5210SJason Evans CTL_PROTO(config_prof) 55a4bd5210SJason Evans CTL_PROTO(config_prof_libgcc) 56a4bd5210SJason Evans CTL_PROTO(config_prof_libunwind) 57a4bd5210SJason Evans CTL_PROTO(config_stats) 58a4bd5210SJason Evans CTL_PROTO(config_tcache) 59a4bd5210SJason Evans CTL_PROTO(config_tls) 60a4bd5210SJason Evans CTL_PROTO(config_utrace) 61a4bd5210SJason Evans CTL_PROTO(config_valgrind) 62a4bd5210SJason Evans CTL_PROTO(config_xmalloc) 63a4bd5210SJason Evans CTL_PROTO(opt_abort) 64a4bd5210SJason Evans CTL_PROTO(opt_lg_chunk) 65a4bd5210SJason Evans CTL_PROTO(opt_narenas) 66a4bd5210SJason Evans CTL_PROTO(opt_lg_dirty_mult) 67a4bd5210SJason Evans CTL_PROTO(opt_stats_print) 68a4bd5210SJason Evans CTL_PROTO(opt_junk) 69a4bd5210SJason Evans CTL_PROTO(opt_zero) 70a4bd5210SJason Evans CTL_PROTO(opt_quarantine) 71a4bd5210SJason Evans CTL_PROTO(opt_redzone) 72a4bd5210SJason Evans CTL_PROTO(opt_utrace) 73a4bd5210SJason Evans CTL_PROTO(opt_valgrind) 74a4bd5210SJason Evans CTL_PROTO(opt_xmalloc) 75a4bd5210SJason Evans CTL_PROTO(opt_tcache) 76a4bd5210SJason Evans CTL_PROTO(opt_lg_tcache_max) 77a4bd5210SJason Evans CTL_PROTO(opt_prof) 78a4bd5210SJason Evans CTL_PROTO(opt_prof_prefix) 79a4bd5210SJason Evans CTL_PROTO(opt_prof_active) 80a4bd5210SJason Evans CTL_PROTO(opt_lg_prof_sample) 81a4bd5210SJason Evans CTL_PROTO(opt_lg_prof_interval) 82a4bd5210SJason Evans CTL_PROTO(opt_prof_gdump) 83*8ed34ab0SJason Evans CTL_PROTO(opt_prof_final) 84a4bd5210SJason Evans CTL_PROTO(opt_prof_leak) 85a4bd5210SJason Evans CTL_PROTO(opt_prof_accum) 86a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_size) 87a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_nregs) 88a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_run_size) 89a4bd5210SJason Evans INDEX_PROTO(arenas_bin_i) 90a4bd5210SJason Evans CTL_PROTO(arenas_lrun_i_size) 91a4bd5210SJason Evans INDEX_PROTO(arenas_lrun_i) 92a4bd5210SJason Evans CTL_PROTO(arenas_narenas) 93a4bd5210SJason Evans CTL_PROTO(arenas_initialized) 94a4bd5210SJason Evans CTL_PROTO(arenas_quantum) 95a4bd5210SJason Evans CTL_PROTO(arenas_page) 96a4bd5210SJason Evans CTL_PROTO(arenas_tcache_max) 97a4bd5210SJason Evans CTL_PROTO(arenas_nbins) 98a4bd5210SJason Evans CTL_PROTO(arenas_nhbins) 99a4bd5210SJason Evans CTL_PROTO(arenas_nlruns) 100a4bd5210SJason Evans CTL_PROTO(arenas_purge) 101a4bd5210SJason Evans CTL_PROTO(prof_active) 102a4bd5210SJason Evans CTL_PROTO(prof_dump) 103a4bd5210SJason Evans CTL_PROTO(prof_interval) 104a4bd5210SJason Evans CTL_PROTO(stats_chunks_current) 105a4bd5210SJason Evans CTL_PROTO(stats_chunks_total) 106a4bd5210SJason Evans CTL_PROTO(stats_chunks_high) 107a4bd5210SJason Evans CTL_PROTO(stats_huge_allocated) 108a4bd5210SJason Evans CTL_PROTO(stats_huge_nmalloc) 109a4bd5210SJason Evans CTL_PROTO(stats_huge_ndalloc) 110a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_allocated) 111a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_nmalloc) 112a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_ndalloc) 113a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_nrequests) 114a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_allocated) 115a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_nmalloc) 116a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_ndalloc) 117a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_nrequests) 118a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_allocated) 119a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nmalloc) 120a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_ndalloc) 121a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nrequests) 122a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nfills) 123a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nflushes) 124a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nruns) 125a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nreruns) 126a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_curruns) 127a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i_bins_j) 128a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_nmalloc) 129a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_ndalloc) 130a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_nrequests) 131a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_curruns) 132a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i_lruns_j) 133a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_nthreads) 134a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_pactive) 135a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_pdirty) 136a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_mapped) 137a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_npurge) 138a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_nmadvise) 139a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_purged) 140a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i) 141a4bd5210SJason Evans CTL_PROTO(stats_cactive) 142a4bd5210SJason Evans CTL_PROTO(stats_allocated) 143a4bd5210SJason Evans CTL_PROTO(stats_active) 144a4bd5210SJason Evans CTL_PROTO(stats_mapped) 145a4bd5210SJason Evans 146a4bd5210SJason Evans /******************************************************************************/ 147a4bd5210SJason Evans /* mallctl tree. */ 148a4bd5210SJason Evans 149a4bd5210SJason Evans /* Maximum tree depth. */ 150a4bd5210SJason Evans #define CTL_MAX_DEPTH 6 151a4bd5210SJason Evans 152a4bd5210SJason Evans #define NAME(n) true, {.named = {n 153a4bd5210SJason Evans #define CHILD(c) sizeof(c##_node) / sizeof(ctl_node_t), c##_node}}, NULL 154a4bd5210SJason Evans #define CTL(c) 0, NULL}}, c##_ctl 155a4bd5210SJason Evans 156a4bd5210SJason Evans /* 157a4bd5210SJason Evans * Only handles internal indexed nodes, since there are currently no external 158a4bd5210SJason Evans * ones. 159a4bd5210SJason Evans */ 160a4bd5210SJason Evans #define INDEX(i) false, {.indexed = {i##_index}}, NULL 161a4bd5210SJason Evans 162a4bd5210SJason Evans static const ctl_node_t tcache_node[] = { 163a4bd5210SJason Evans {NAME("enabled"), CTL(thread_tcache_enabled)}, 164a4bd5210SJason Evans {NAME("flush"), CTL(thread_tcache_flush)} 165a4bd5210SJason Evans }; 166a4bd5210SJason Evans 167a4bd5210SJason Evans static const ctl_node_t thread_node[] = { 168a4bd5210SJason Evans {NAME("arena"), CTL(thread_arena)}, 169a4bd5210SJason Evans {NAME("allocated"), CTL(thread_allocated)}, 170a4bd5210SJason Evans {NAME("allocatedp"), CTL(thread_allocatedp)}, 171a4bd5210SJason Evans {NAME("deallocated"), CTL(thread_deallocated)}, 172a4bd5210SJason Evans {NAME("deallocatedp"), CTL(thread_deallocatedp)}, 173a4bd5210SJason Evans {NAME("tcache"), CHILD(tcache)} 174a4bd5210SJason Evans }; 175a4bd5210SJason Evans 176a4bd5210SJason Evans static const ctl_node_t config_node[] = { 177a4bd5210SJason Evans {NAME("debug"), CTL(config_debug)}, 178a4bd5210SJason Evans {NAME("dss"), CTL(config_dss)}, 179a4bd5210SJason Evans {NAME("fill"), CTL(config_fill)}, 180a4bd5210SJason Evans {NAME("lazy_lock"), CTL(config_lazy_lock)}, 181a4bd5210SJason Evans {NAME("munmap"), CTL(config_munmap)}, 182a4bd5210SJason Evans {NAME("prof"), CTL(config_prof)}, 183a4bd5210SJason Evans {NAME("prof_libgcc"), CTL(config_prof_libgcc)}, 184a4bd5210SJason Evans {NAME("prof_libunwind"), CTL(config_prof_libunwind)}, 185a4bd5210SJason Evans {NAME("stats"), CTL(config_stats)}, 186a4bd5210SJason Evans {NAME("tcache"), CTL(config_tcache)}, 187a4bd5210SJason Evans {NAME("tls"), CTL(config_tls)}, 188a4bd5210SJason Evans {NAME("utrace"), CTL(config_utrace)}, 189a4bd5210SJason Evans {NAME("valgrind"), CTL(config_valgrind)}, 190a4bd5210SJason Evans {NAME("xmalloc"), CTL(config_xmalloc)} 191a4bd5210SJason Evans }; 192a4bd5210SJason Evans 193a4bd5210SJason Evans static const ctl_node_t opt_node[] = { 194a4bd5210SJason Evans {NAME("abort"), CTL(opt_abort)}, 195a4bd5210SJason Evans {NAME("lg_chunk"), CTL(opt_lg_chunk)}, 196a4bd5210SJason Evans {NAME("narenas"), CTL(opt_narenas)}, 197a4bd5210SJason Evans {NAME("lg_dirty_mult"), CTL(opt_lg_dirty_mult)}, 198a4bd5210SJason Evans {NAME("stats_print"), CTL(opt_stats_print)}, 199a4bd5210SJason Evans {NAME("junk"), CTL(opt_junk)}, 200a4bd5210SJason Evans {NAME("zero"), CTL(opt_zero)}, 201a4bd5210SJason Evans {NAME("quarantine"), CTL(opt_quarantine)}, 202a4bd5210SJason Evans {NAME("redzone"), CTL(opt_redzone)}, 203a4bd5210SJason Evans {NAME("utrace"), CTL(opt_utrace)}, 204a4bd5210SJason Evans {NAME("valgrind"), CTL(opt_valgrind)}, 205a4bd5210SJason Evans {NAME("xmalloc"), CTL(opt_xmalloc)}, 206a4bd5210SJason Evans {NAME("tcache"), CTL(opt_tcache)}, 207a4bd5210SJason Evans {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)}, 208a4bd5210SJason Evans {NAME("prof"), CTL(opt_prof)}, 209a4bd5210SJason Evans {NAME("prof_prefix"), CTL(opt_prof_prefix)}, 210a4bd5210SJason Evans {NAME("prof_active"), CTL(opt_prof_active)}, 211a4bd5210SJason Evans {NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)}, 212a4bd5210SJason Evans {NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)}, 213a4bd5210SJason Evans {NAME("prof_gdump"), CTL(opt_prof_gdump)}, 214*8ed34ab0SJason Evans {NAME("prof_final"), CTL(opt_prof_final)}, 215a4bd5210SJason Evans {NAME("prof_leak"), CTL(opt_prof_leak)}, 216a4bd5210SJason Evans {NAME("prof_accum"), CTL(opt_prof_accum)} 217a4bd5210SJason Evans }; 218a4bd5210SJason Evans 219a4bd5210SJason Evans static const ctl_node_t arenas_bin_i_node[] = { 220a4bd5210SJason Evans {NAME("size"), CTL(arenas_bin_i_size)}, 221a4bd5210SJason Evans {NAME("nregs"), CTL(arenas_bin_i_nregs)}, 222a4bd5210SJason Evans {NAME("run_size"), CTL(arenas_bin_i_run_size)} 223a4bd5210SJason Evans }; 224a4bd5210SJason Evans static const ctl_node_t super_arenas_bin_i_node[] = { 225a4bd5210SJason Evans {NAME(""), CHILD(arenas_bin_i)} 226a4bd5210SJason Evans }; 227a4bd5210SJason Evans 228a4bd5210SJason Evans static const ctl_node_t arenas_bin_node[] = { 229a4bd5210SJason Evans {INDEX(arenas_bin_i)} 230a4bd5210SJason Evans }; 231a4bd5210SJason Evans 232a4bd5210SJason Evans static const ctl_node_t arenas_lrun_i_node[] = { 233a4bd5210SJason Evans {NAME("size"), CTL(arenas_lrun_i_size)} 234a4bd5210SJason Evans }; 235a4bd5210SJason Evans static const ctl_node_t super_arenas_lrun_i_node[] = { 236a4bd5210SJason Evans {NAME(""), CHILD(arenas_lrun_i)} 237a4bd5210SJason Evans }; 238a4bd5210SJason Evans 239a4bd5210SJason Evans static const ctl_node_t arenas_lrun_node[] = { 240a4bd5210SJason Evans {INDEX(arenas_lrun_i)} 241a4bd5210SJason Evans }; 242a4bd5210SJason Evans 243a4bd5210SJason Evans static const ctl_node_t arenas_node[] = { 244a4bd5210SJason Evans {NAME("narenas"), CTL(arenas_narenas)}, 245a4bd5210SJason Evans {NAME("initialized"), CTL(arenas_initialized)}, 246a4bd5210SJason Evans {NAME("quantum"), CTL(arenas_quantum)}, 247a4bd5210SJason Evans {NAME("page"), CTL(arenas_page)}, 248a4bd5210SJason Evans {NAME("tcache_max"), CTL(arenas_tcache_max)}, 249a4bd5210SJason Evans {NAME("nbins"), CTL(arenas_nbins)}, 250a4bd5210SJason Evans {NAME("nhbins"), CTL(arenas_nhbins)}, 251a4bd5210SJason Evans {NAME("bin"), CHILD(arenas_bin)}, 252a4bd5210SJason Evans {NAME("nlruns"), CTL(arenas_nlruns)}, 253a4bd5210SJason Evans {NAME("lrun"), CHILD(arenas_lrun)}, 254a4bd5210SJason Evans {NAME("purge"), CTL(arenas_purge)} 255a4bd5210SJason Evans }; 256a4bd5210SJason Evans 257a4bd5210SJason Evans static const ctl_node_t prof_node[] = { 258a4bd5210SJason Evans {NAME("active"), CTL(prof_active)}, 259a4bd5210SJason Evans {NAME("dump"), CTL(prof_dump)}, 260a4bd5210SJason Evans {NAME("interval"), CTL(prof_interval)} 261a4bd5210SJason Evans }; 262a4bd5210SJason Evans 263a4bd5210SJason Evans static const ctl_node_t stats_chunks_node[] = { 264a4bd5210SJason Evans {NAME("current"), CTL(stats_chunks_current)}, 265a4bd5210SJason Evans {NAME("total"), CTL(stats_chunks_total)}, 266a4bd5210SJason Evans {NAME("high"), CTL(stats_chunks_high)} 267a4bd5210SJason Evans }; 268a4bd5210SJason Evans 269a4bd5210SJason Evans static const ctl_node_t stats_huge_node[] = { 270a4bd5210SJason Evans {NAME("allocated"), CTL(stats_huge_allocated)}, 271a4bd5210SJason Evans {NAME("nmalloc"), CTL(stats_huge_nmalloc)}, 272a4bd5210SJason Evans {NAME("ndalloc"), CTL(stats_huge_ndalloc)} 273a4bd5210SJason Evans }; 274a4bd5210SJason Evans 275a4bd5210SJason Evans static const ctl_node_t stats_arenas_i_small_node[] = { 276a4bd5210SJason Evans {NAME("allocated"), CTL(stats_arenas_i_small_allocated)}, 277a4bd5210SJason Evans {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)}, 278a4bd5210SJason Evans {NAME("ndalloc"), CTL(stats_arenas_i_small_ndalloc)}, 279a4bd5210SJason Evans {NAME("nrequests"), CTL(stats_arenas_i_small_nrequests)} 280a4bd5210SJason Evans }; 281a4bd5210SJason Evans 282a4bd5210SJason Evans static const ctl_node_t stats_arenas_i_large_node[] = { 283a4bd5210SJason Evans {NAME("allocated"), CTL(stats_arenas_i_large_allocated)}, 284a4bd5210SJason Evans {NAME("nmalloc"), CTL(stats_arenas_i_large_nmalloc)}, 285a4bd5210SJason Evans {NAME("ndalloc"), CTL(stats_arenas_i_large_ndalloc)}, 286a4bd5210SJason Evans {NAME("nrequests"), CTL(stats_arenas_i_large_nrequests)} 287a4bd5210SJason Evans }; 288a4bd5210SJason Evans 289a4bd5210SJason Evans static const ctl_node_t stats_arenas_i_bins_j_node[] = { 290a4bd5210SJason Evans {NAME("allocated"), CTL(stats_arenas_i_bins_j_allocated)}, 291a4bd5210SJason Evans {NAME("nmalloc"), CTL(stats_arenas_i_bins_j_nmalloc)}, 292a4bd5210SJason Evans {NAME("ndalloc"), CTL(stats_arenas_i_bins_j_ndalloc)}, 293a4bd5210SJason Evans {NAME("nrequests"), CTL(stats_arenas_i_bins_j_nrequests)}, 294a4bd5210SJason Evans {NAME("nfills"), CTL(stats_arenas_i_bins_j_nfills)}, 295a4bd5210SJason Evans {NAME("nflushes"), CTL(stats_arenas_i_bins_j_nflushes)}, 296a4bd5210SJason Evans {NAME("nruns"), CTL(stats_arenas_i_bins_j_nruns)}, 297a4bd5210SJason Evans {NAME("nreruns"), CTL(stats_arenas_i_bins_j_nreruns)}, 298a4bd5210SJason Evans {NAME("curruns"), CTL(stats_arenas_i_bins_j_curruns)} 299a4bd5210SJason Evans }; 300a4bd5210SJason Evans static const ctl_node_t super_stats_arenas_i_bins_j_node[] = { 301a4bd5210SJason Evans {NAME(""), CHILD(stats_arenas_i_bins_j)} 302a4bd5210SJason Evans }; 303a4bd5210SJason Evans 304a4bd5210SJason Evans static const ctl_node_t stats_arenas_i_bins_node[] = { 305a4bd5210SJason Evans {INDEX(stats_arenas_i_bins_j)} 306a4bd5210SJason Evans }; 307a4bd5210SJason Evans 308a4bd5210SJason Evans static const ctl_node_t stats_arenas_i_lruns_j_node[] = { 309a4bd5210SJason Evans {NAME("nmalloc"), CTL(stats_arenas_i_lruns_j_nmalloc)}, 310a4bd5210SJason Evans {NAME("ndalloc"), CTL(stats_arenas_i_lruns_j_ndalloc)}, 311a4bd5210SJason Evans {NAME("nrequests"), CTL(stats_arenas_i_lruns_j_nrequests)}, 312a4bd5210SJason Evans {NAME("curruns"), CTL(stats_arenas_i_lruns_j_curruns)} 313a4bd5210SJason Evans }; 314a4bd5210SJason Evans static const ctl_node_t super_stats_arenas_i_lruns_j_node[] = { 315a4bd5210SJason Evans {NAME(""), CHILD(stats_arenas_i_lruns_j)} 316a4bd5210SJason Evans }; 317a4bd5210SJason Evans 318a4bd5210SJason Evans static const ctl_node_t stats_arenas_i_lruns_node[] = { 319a4bd5210SJason Evans {INDEX(stats_arenas_i_lruns_j)} 320a4bd5210SJason Evans }; 321a4bd5210SJason Evans 322a4bd5210SJason Evans static const ctl_node_t stats_arenas_i_node[] = { 323a4bd5210SJason Evans {NAME("nthreads"), CTL(stats_arenas_i_nthreads)}, 324a4bd5210SJason Evans {NAME("pactive"), CTL(stats_arenas_i_pactive)}, 325a4bd5210SJason Evans {NAME("pdirty"), CTL(stats_arenas_i_pdirty)}, 326a4bd5210SJason Evans {NAME("mapped"), CTL(stats_arenas_i_mapped)}, 327a4bd5210SJason Evans {NAME("npurge"), CTL(stats_arenas_i_npurge)}, 328a4bd5210SJason Evans {NAME("nmadvise"), CTL(stats_arenas_i_nmadvise)}, 329a4bd5210SJason Evans {NAME("purged"), CTL(stats_arenas_i_purged)}, 330a4bd5210SJason Evans {NAME("small"), CHILD(stats_arenas_i_small)}, 331a4bd5210SJason Evans {NAME("large"), CHILD(stats_arenas_i_large)}, 332a4bd5210SJason Evans {NAME("bins"), CHILD(stats_arenas_i_bins)}, 333a4bd5210SJason Evans {NAME("lruns"), CHILD(stats_arenas_i_lruns)} 334a4bd5210SJason Evans }; 335a4bd5210SJason Evans static const ctl_node_t super_stats_arenas_i_node[] = { 336a4bd5210SJason Evans {NAME(""), CHILD(stats_arenas_i)} 337a4bd5210SJason Evans }; 338a4bd5210SJason Evans 339a4bd5210SJason Evans static const ctl_node_t stats_arenas_node[] = { 340a4bd5210SJason Evans {INDEX(stats_arenas_i)} 341a4bd5210SJason Evans }; 342a4bd5210SJason Evans 343a4bd5210SJason Evans static const ctl_node_t stats_node[] = { 344a4bd5210SJason Evans {NAME("cactive"), CTL(stats_cactive)}, 345a4bd5210SJason Evans {NAME("allocated"), CTL(stats_allocated)}, 346a4bd5210SJason Evans {NAME("active"), CTL(stats_active)}, 347a4bd5210SJason Evans {NAME("mapped"), CTL(stats_mapped)}, 348a4bd5210SJason Evans {NAME("chunks"), CHILD(stats_chunks)}, 349a4bd5210SJason Evans {NAME("huge"), CHILD(stats_huge)}, 350a4bd5210SJason Evans {NAME("arenas"), CHILD(stats_arenas)} 351a4bd5210SJason Evans }; 352a4bd5210SJason Evans 353a4bd5210SJason Evans static const ctl_node_t root_node[] = { 354a4bd5210SJason Evans {NAME("version"), CTL(version)}, 355a4bd5210SJason Evans {NAME("epoch"), CTL(epoch)}, 356a4bd5210SJason Evans {NAME("thread"), CHILD(thread)}, 357a4bd5210SJason Evans {NAME("config"), CHILD(config)}, 358a4bd5210SJason Evans {NAME("opt"), CHILD(opt)}, 359a4bd5210SJason Evans {NAME("arenas"), CHILD(arenas)}, 360a4bd5210SJason Evans {NAME("prof"), CHILD(prof)}, 361a4bd5210SJason Evans {NAME("stats"), CHILD(stats)} 362a4bd5210SJason Evans }; 363a4bd5210SJason Evans static const ctl_node_t super_root_node[] = { 364a4bd5210SJason Evans {NAME(""), CHILD(root)} 365a4bd5210SJason Evans }; 366a4bd5210SJason Evans 367a4bd5210SJason Evans #undef NAME 368a4bd5210SJason Evans #undef CHILD 369a4bd5210SJason Evans #undef CTL 370a4bd5210SJason Evans #undef INDEX 371a4bd5210SJason Evans 372a4bd5210SJason Evans /******************************************************************************/ 373a4bd5210SJason Evans 374a4bd5210SJason Evans static bool 375a4bd5210SJason Evans ctl_arena_init(ctl_arena_stats_t *astats) 376a4bd5210SJason Evans { 377a4bd5210SJason Evans 378a4bd5210SJason Evans if (astats->lstats == NULL) { 379a4bd5210SJason Evans astats->lstats = (malloc_large_stats_t *)base_alloc(nlclasses * 380a4bd5210SJason Evans sizeof(malloc_large_stats_t)); 381a4bd5210SJason Evans if (astats->lstats == NULL) 382a4bd5210SJason Evans return (true); 383a4bd5210SJason Evans } 384a4bd5210SJason Evans 385a4bd5210SJason Evans return (false); 386a4bd5210SJason Evans } 387a4bd5210SJason Evans 388a4bd5210SJason Evans static void 389a4bd5210SJason Evans ctl_arena_clear(ctl_arena_stats_t *astats) 390a4bd5210SJason Evans { 391a4bd5210SJason Evans 392a4bd5210SJason Evans astats->pactive = 0; 393a4bd5210SJason Evans astats->pdirty = 0; 394a4bd5210SJason Evans if (config_stats) { 395a4bd5210SJason Evans memset(&astats->astats, 0, sizeof(arena_stats_t)); 396a4bd5210SJason Evans astats->allocated_small = 0; 397a4bd5210SJason Evans astats->nmalloc_small = 0; 398a4bd5210SJason Evans astats->ndalloc_small = 0; 399a4bd5210SJason Evans astats->nrequests_small = 0; 400a4bd5210SJason Evans memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t)); 401a4bd5210SJason Evans memset(astats->lstats, 0, nlclasses * 402a4bd5210SJason Evans sizeof(malloc_large_stats_t)); 403a4bd5210SJason Evans } 404a4bd5210SJason Evans } 405a4bd5210SJason Evans 406a4bd5210SJason Evans static void 407a4bd5210SJason Evans ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena) 408a4bd5210SJason Evans { 409a4bd5210SJason Evans unsigned i; 410a4bd5210SJason Evans 411a4bd5210SJason Evans arena_stats_merge(arena, &cstats->pactive, &cstats->pdirty, 412a4bd5210SJason Evans &cstats->astats, cstats->bstats, cstats->lstats); 413a4bd5210SJason Evans 414a4bd5210SJason Evans for (i = 0; i < NBINS; i++) { 415a4bd5210SJason Evans cstats->allocated_small += cstats->bstats[i].allocated; 416a4bd5210SJason Evans cstats->nmalloc_small += cstats->bstats[i].nmalloc; 417a4bd5210SJason Evans cstats->ndalloc_small += cstats->bstats[i].ndalloc; 418a4bd5210SJason Evans cstats->nrequests_small += cstats->bstats[i].nrequests; 419a4bd5210SJason Evans } 420a4bd5210SJason Evans } 421a4bd5210SJason Evans 422a4bd5210SJason Evans static void 423a4bd5210SJason Evans ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats) 424a4bd5210SJason Evans { 425a4bd5210SJason Evans unsigned i; 426a4bd5210SJason Evans 427a4bd5210SJason Evans sstats->pactive += astats->pactive; 428a4bd5210SJason Evans sstats->pdirty += astats->pdirty; 429a4bd5210SJason Evans 430a4bd5210SJason Evans sstats->astats.mapped += astats->astats.mapped; 431a4bd5210SJason Evans sstats->astats.npurge += astats->astats.npurge; 432a4bd5210SJason Evans sstats->astats.nmadvise += astats->astats.nmadvise; 433a4bd5210SJason Evans sstats->astats.purged += astats->astats.purged; 434a4bd5210SJason Evans 435a4bd5210SJason Evans sstats->allocated_small += astats->allocated_small; 436a4bd5210SJason Evans sstats->nmalloc_small += astats->nmalloc_small; 437a4bd5210SJason Evans sstats->ndalloc_small += astats->ndalloc_small; 438a4bd5210SJason Evans sstats->nrequests_small += astats->nrequests_small; 439a4bd5210SJason Evans 440a4bd5210SJason Evans sstats->astats.allocated_large += astats->astats.allocated_large; 441a4bd5210SJason Evans sstats->astats.nmalloc_large += astats->astats.nmalloc_large; 442a4bd5210SJason Evans sstats->astats.ndalloc_large += astats->astats.ndalloc_large; 443a4bd5210SJason Evans sstats->astats.nrequests_large += astats->astats.nrequests_large; 444a4bd5210SJason Evans 445a4bd5210SJason Evans for (i = 0; i < nlclasses; i++) { 446a4bd5210SJason Evans sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc; 447a4bd5210SJason Evans sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc; 448a4bd5210SJason Evans sstats->lstats[i].nrequests += astats->lstats[i].nrequests; 449a4bd5210SJason Evans sstats->lstats[i].curruns += astats->lstats[i].curruns; 450a4bd5210SJason Evans } 451a4bd5210SJason Evans 452a4bd5210SJason Evans for (i = 0; i < NBINS; i++) { 453a4bd5210SJason Evans sstats->bstats[i].allocated += astats->bstats[i].allocated; 454a4bd5210SJason Evans sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc; 455a4bd5210SJason Evans sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc; 456a4bd5210SJason Evans sstats->bstats[i].nrequests += astats->bstats[i].nrequests; 457a4bd5210SJason Evans if (config_tcache) { 458a4bd5210SJason Evans sstats->bstats[i].nfills += astats->bstats[i].nfills; 459a4bd5210SJason Evans sstats->bstats[i].nflushes += 460a4bd5210SJason Evans astats->bstats[i].nflushes; 461a4bd5210SJason Evans } 462a4bd5210SJason Evans sstats->bstats[i].nruns += astats->bstats[i].nruns; 463a4bd5210SJason Evans sstats->bstats[i].reruns += astats->bstats[i].reruns; 464a4bd5210SJason Evans sstats->bstats[i].curruns += astats->bstats[i].curruns; 465a4bd5210SJason Evans } 466a4bd5210SJason Evans } 467a4bd5210SJason Evans 468a4bd5210SJason Evans static void 469a4bd5210SJason Evans ctl_arena_refresh(arena_t *arena, unsigned i) 470a4bd5210SJason Evans { 471a4bd5210SJason Evans ctl_arena_stats_t *astats = &ctl_stats.arenas[i]; 472a4bd5210SJason Evans ctl_arena_stats_t *sstats = &ctl_stats.arenas[narenas]; 473a4bd5210SJason Evans 474a4bd5210SJason Evans ctl_arena_clear(astats); 475a4bd5210SJason Evans 476a4bd5210SJason Evans sstats->nthreads += astats->nthreads; 477a4bd5210SJason Evans if (config_stats) { 478a4bd5210SJason Evans ctl_arena_stats_amerge(astats, arena); 479a4bd5210SJason Evans /* Merge into sum stats as well. */ 480a4bd5210SJason Evans ctl_arena_stats_smerge(sstats, astats); 481a4bd5210SJason Evans } else { 482a4bd5210SJason Evans astats->pactive += arena->nactive; 483a4bd5210SJason Evans astats->pdirty += arena->ndirty; 484a4bd5210SJason Evans /* Merge into sum stats as well. */ 485a4bd5210SJason Evans sstats->pactive += arena->nactive; 486a4bd5210SJason Evans sstats->pdirty += arena->ndirty; 487a4bd5210SJason Evans } 488a4bd5210SJason Evans } 489a4bd5210SJason Evans 490a4bd5210SJason Evans static void 491a4bd5210SJason Evans ctl_refresh(void) 492a4bd5210SJason Evans { 493a4bd5210SJason Evans unsigned i; 494a4bd5210SJason Evans arena_t *tarenas[narenas]; 495a4bd5210SJason Evans 496a4bd5210SJason Evans if (config_stats) { 497a4bd5210SJason Evans malloc_mutex_lock(&chunks_mtx); 498a4bd5210SJason Evans ctl_stats.chunks.current = stats_chunks.curchunks; 499a4bd5210SJason Evans ctl_stats.chunks.total = stats_chunks.nchunks; 500a4bd5210SJason Evans ctl_stats.chunks.high = stats_chunks.highchunks; 501a4bd5210SJason Evans malloc_mutex_unlock(&chunks_mtx); 502a4bd5210SJason Evans 503a4bd5210SJason Evans malloc_mutex_lock(&huge_mtx); 504a4bd5210SJason Evans ctl_stats.huge.allocated = huge_allocated; 505a4bd5210SJason Evans ctl_stats.huge.nmalloc = huge_nmalloc; 506a4bd5210SJason Evans ctl_stats.huge.ndalloc = huge_ndalloc; 507a4bd5210SJason Evans malloc_mutex_unlock(&huge_mtx); 508a4bd5210SJason Evans } 509a4bd5210SJason Evans 510a4bd5210SJason Evans /* 511a4bd5210SJason Evans * Clear sum stats, since they will be merged into by 512a4bd5210SJason Evans * ctl_arena_refresh(). 513a4bd5210SJason Evans */ 514a4bd5210SJason Evans ctl_stats.arenas[narenas].nthreads = 0; 515a4bd5210SJason Evans ctl_arena_clear(&ctl_stats.arenas[narenas]); 516a4bd5210SJason Evans 517a4bd5210SJason Evans malloc_mutex_lock(&arenas_lock); 518a4bd5210SJason Evans memcpy(tarenas, arenas, sizeof(arena_t *) * narenas); 519a4bd5210SJason Evans for (i = 0; i < narenas; i++) { 520a4bd5210SJason Evans if (arenas[i] != NULL) 521a4bd5210SJason Evans ctl_stats.arenas[i].nthreads = arenas[i]->nthreads; 522a4bd5210SJason Evans else 523a4bd5210SJason Evans ctl_stats.arenas[i].nthreads = 0; 524a4bd5210SJason Evans } 525a4bd5210SJason Evans malloc_mutex_unlock(&arenas_lock); 526a4bd5210SJason Evans for (i = 0; i < narenas; i++) { 527a4bd5210SJason Evans bool initialized = (tarenas[i] != NULL); 528a4bd5210SJason Evans 529a4bd5210SJason Evans ctl_stats.arenas[i].initialized = initialized; 530a4bd5210SJason Evans if (initialized) 531a4bd5210SJason Evans ctl_arena_refresh(tarenas[i], i); 532a4bd5210SJason Evans } 533a4bd5210SJason Evans 534a4bd5210SJason Evans if (config_stats) { 535a4bd5210SJason Evans ctl_stats.allocated = ctl_stats.arenas[narenas].allocated_small 536a4bd5210SJason Evans + ctl_stats.arenas[narenas].astats.allocated_large 537a4bd5210SJason Evans + ctl_stats.huge.allocated; 538a4bd5210SJason Evans ctl_stats.active = (ctl_stats.arenas[narenas].pactive << 539a4bd5210SJason Evans LG_PAGE) + ctl_stats.huge.allocated; 540a4bd5210SJason Evans ctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk); 541a4bd5210SJason Evans } 542a4bd5210SJason Evans 543a4bd5210SJason Evans ctl_epoch++; 544a4bd5210SJason Evans } 545a4bd5210SJason Evans 546a4bd5210SJason Evans static bool 547a4bd5210SJason Evans ctl_init(void) 548a4bd5210SJason Evans { 549a4bd5210SJason Evans bool ret; 550a4bd5210SJason Evans 551a4bd5210SJason Evans malloc_mutex_lock(&ctl_mtx); 552a4bd5210SJason Evans if (ctl_initialized == false) { 553a4bd5210SJason Evans /* 554a4bd5210SJason Evans * Allocate space for one extra arena stats element, which 555a4bd5210SJason Evans * contains summed stats across all arenas. 556a4bd5210SJason Evans */ 557a4bd5210SJason Evans ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc( 558a4bd5210SJason Evans (narenas + 1) * sizeof(ctl_arena_stats_t)); 559a4bd5210SJason Evans if (ctl_stats.arenas == NULL) { 560a4bd5210SJason Evans ret = true; 561a4bd5210SJason Evans goto label_return; 562a4bd5210SJason Evans } 563a4bd5210SJason Evans memset(ctl_stats.arenas, 0, (narenas + 1) * 564a4bd5210SJason Evans sizeof(ctl_arena_stats_t)); 565a4bd5210SJason Evans 566a4bd5210SJason Evans /* 567a4bd5210SJason Evans * Initialize all stats structures, regardless of whether they 568a4bd5210SJason Evans * ever get used. Lazy initialization would allow errors to 569a4bd5210SJason Evans * cause inconsistent state to be viewable by the application. 570a4bd5210SJason Evans */ 571a4bd5210SJason Evans if (config_stats) { 572a4bd5210SJason Evans unsigned i; 573a4bd5210SJason Evans for (i = 0; i <= narenas; i++) { 574a4bd5210SJason Evans if (ctl_arena_init(&ctl_stats.arenas[i])) { 575a4bd5210SJason Evans ret = true; 576a4bd5210SJason Evans goto label_return; 577a4bd5210SJason Evans } 578a4bd5210SJason Evans } 579a4bd5210SJason Evans } 580a4bd5210SJason Evans ctl_stats.arenas[narenas].initialized = true; 581a4bd5210SJason Evans 582a4bd5210SJason Evans ctl_epoch = 0; 583a4bd5210SJason Evans ctl_refresh(); 584a4bd5210SJason Evans ctl_initialized = true; 585a4bd5210SJason Evans } 586a4bd5210SJason Evans 587a4bd5210SJason Evans ret = false; 588a4bd5210SJason Evans label_return: 589a4bd5210SJason Evans malloc_mutex_unlock(&ctl_mtx); 590a4bd5210SJason Evans return (ret); 591a4bd5210SJason Evans } 592a4bd5210SJason Evans 593a4bd5210SJason Evans static int 594a4bd5210SJason Evans ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp, 595a4bd5210SJason Evans size_t *depthp) 596a4bd5210SJason Evans { 597a4bd5210SJason Evans int ret; 598a4bd5210SJason Evans const char *elm, *tdot, *dot; 599a4bd5210SJason Evans size_t elen, i, j; 600a4bd5210SJason Evans const ctl_node_t *node; 601a4bd5210SJason Evans 602a4bd5210SJason Evans elm = name; 603a4bd5210SJason Evans /* Equivalent to strchrnul(). */ 604a4bd5210SJason Evans dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0'); 605a4bd5210SJason Evans elen = (size_t)((uintptr_t)dot - (uintptr_t)elm); 606a4bd5210SJason Evans if (elen == 0) { 607a4bd5210SJason Evans ret = ENOENT; 608a4bd5210SJason Evans goto label_return; 609a4bd5210SJason Evans } 610a4bd5210SJason Evans node = super_root_node; 611a4bd5210SJason Evans for (i = 0; i < *depthp; i++) { 612a4bd5210SJason Evans assert(node->named); 613a4bd5210SJason Evans assert(node->u.named.nchildren > 0); 614a4bd5210SJason Evans if (node->u.named.children[0].named) { 615a4bd5210SJason Evans const ctl_node_t *pnode = node; 616a4bd5210SJason Evans 617a4bd5210SJason Evans /* Children are named. */ 618a4bd5210SJason Evans for (j = 0; j < node->u.named.nchildren; j++) { 619a4bd5210SJason Evans const ctl_node_t *child = 620a4bd5210SJason Evans &node->u.named.children[j]; 621a4bd5210SJason Evans if (strlen(child->u.named.name) == elen 622a4bd5210SJason Evans && strncmp(elm, child->u.named.name, 623a4bd5210SJason Evans elen) == 0) { 624a4bd5210SJason Evans node = child; 625a4bd5210SJason Evans if (nodesp != NULL) 626a4bd5210SJason Evans nodesp[i] = node; 627a4bd5210SJason Evans mibp[i] = j; 628a4bd5210SJason Evans break; 629a4bd5210SJason Evans } 630a4bd5210SJason Evans } 631a4bd5210SJason Evans if (node == pnode) { 632a4bd5210SJason Evans ret = ENOENT; 633a4bd5210SJason Evans goto label_return; 634a4bd5210SJason Evans } 635a4bd5210SJason Evans } else { 636a4bd5210SJason Evans uintmax_t index; 637a4bd5210SJason Evans const ctl_node_t *inode; 638a4bd5210SJason Evans 639a4bd5210SJason Evans /* Children are indexed. */ 640a4bd5210SJason Evans index = malloc_strtoumax(elm, NULL, 10); 641a4bd5210SJason Evans if (index == UINTMAX_MAX || index > SIZE_T_MAX) { 642a4bd5210SJason Evans ret = ENOENT; 643a4bd5210SJason Evans goto label_return; 644a4bd5210SJason Evans } 645a4bd5210SJason Evans 646a4bd5210SJason Evans inode = &node->u.named.children[0]; 647a4bd5210SJason Evans node = inode->u.indexed.index(mibp, *depthp, 648a4bd5210SJason Evans (size_t)index); 649a4bd5210SJason Evans if (node == NULL) { 650a4bd5210SJason Evans ret = ENOENT; 651a4bd5210SJason Evans goto label_return; 652a4bd5210SJason Evans } 653a4bd5210SJason Evans 654a4bd5210SJason Evans if (nodesp != NULL) 655a4bd5210SJason Evans nodesp[i] = node; 656a4bd5210SJason Evans mibp[i] = (size_t)index; 657a4bd5210SJason Evans } 658a4bd5210SJason Evans 659a4bd5210SJason Evans if (node->ctl != NULL) { 660a4bd5210SJason Evans /* Terminal node. */ 661a4bd5210SJason Evans if (*dot != '\0') { 662a4bd5210SJason Evans /* 663a4bd5210SJason Evans * The name contains more elements than are 664a4bd5210SJason Evans * in this path through the tree. 665a4bd5210SJason Evans */ 666a4bd5210SJason Evans ret = ENOENT; 667a4bd5210SJason Evans goto label_return; 668a4bd5210SJason Evans } 669a4bd5210SJason Evans /* Complete lookup successful. */ 670a4bd5210SJason Evans *depthp = i + 1; 671a4bd5210SJason Evans break; 672a4bd5210SJason Evans } 673a4bd5210SJason Evans 674a4bd5210SJason Evans /* Update elm. */ 675a4bd5210SJason Evans if (*dot == '\0') { 676a4bd5210SJason Evans /* No more elements. */ 677a4bd5210SJason Evans ret = ENOENT; 678a4bd5210SJason Evans goto label_return; 679a4bd5210SJason Evans } 680a4bd5210SJason Evans elm = &dot[1]; 681a4bd5210SJason Evans dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : 682a4bd5210SJason Evans strchr(elm, '\0'); 683a4bd5210SJason Evans elen = (size_t)((uintptr_t)dot - (uintptr_t)elm); 684a4bd5210SJason Evans } 685a4bd5210SJason Evans 686a4bd5210SJason Evans ret = 0; 687a4bd5210SJason Evans label_return: 688a4bd5210SJason Evans return (ret); 689a4bd5210SJason Evans } 690a4bd5210SJason Evans 691a4bd5210SJason Evans int 692a4bd5210SJason Evans ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp, 693a4bd5210SJason Evans size_t newlen) 694a4bd5210SJason Evans { 695a4bd5210SJason Evans int ret; 696a4bd5210SJason Evans size_t depth; 697a4bd5210SJason Evans ctl_node_t const *nodes[CTL_MAX_DEPTH]; 698a4bd5210SJason Evans size_t mib[CTL_MAX_DEPTH]; 699a4bd5210SJason Evans 700a4bd5210SJason Evans if (ctl_initialized == false && ctl_init()) { 701a4bd5210SJason Evans ret = EAGAIN; 702a4bd5210SJason Evans goto label_return; 703a4bd5210SJason Evans } 704a4bd5210SJason Evans 705a4bd5210SJason Evans depth = CTL_MAX_DEPTH; 706a4bd5210SJason Evans ret = ctl_lookup(name, nodes, mib, &depth); 707a4bd5210SJason Evans if (ret != 0) 708a4bd5210SJason Evans goto label_return; 709a4bd5210SJason Evans 710a4bd5210SJason Evans if (nodes[depth-1]->ctl == NULL) { 711a4bd5210SJason Evans /* The name refers to a partial path through the ctl tree. */ 712a4bd5210SJason Evans ret = ENOENT; 713a4bd5210SJason Evans goto label_return; 714a4bd5210SJason Evans } 715a4bd5210SJason Evans 716a4bd5210SJason Evans ret = nodes[depth-1]->ctl(mib, depth, oldp, oldlenp, newp, newlen); 717a4bd5210SJason Evans label_return: 718a4bd5210SJason Evans return(ret); 719a4bd5210SJason Evans } 720a4bd5210SJason Evans 721a4bd5210SJason Evans int 722a4bd5210SJason Evans ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp) 723a4bd5210SJason Evans { 724a4bd5210SJason Evans int ret; 725a4bd5210SJason Evans 726a4bd5210SJason Evans if (ctl_initialized == false && ctl_init()) { 727a4bd5210SJason Evans ret = EAGAIN; 728a4bd5210SJason Evans goto label_return; 729a4bd5210SJason Evans } 730a4bd5210SJason Evans 731a4bd5210SJason Evans ret = ctl_lookup(name, NULL, mibp, miblenp); 732a4bd5210SJason Evans label_return: 733a4bd5210SJason Evans return(ret); 734a4bd5210SJason Evans } 735a4bd5210SJason Evans 736a4bd5210SJason Evans int 737a4bd5210SJason Evans ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, 738a4bd5210SJason Evans void *newp, size_t newlen) 739a4bd5210SJason Evans { 740a4bd5210SJason Evans int ret; 741a4bd5210SJason Evans const ctl_node_t *node; 742a4bd5210SJason Evans size_t i; 743a4bd5210SJason Evans 744a4bd5210SJason Evans if (ctl_initialized == false && ctl_init()) { 745a4bd5210SJason Evans ret = EAGAIN; 746a4bd5210SJason Evans goto label_return; 747a4bd5210SJason Evans } 748a4bd5210SJason Evans 749a4bd5210SJason Evans /* Iterate down the tree. */ 750a4bd5210SJason Evans node = super_root_node; 751a4bd5210SJason Evans for (i = 0; i < miblen; i++) { 752a4bd5210SJason Evans if (node->u.named.children[0].named) { 753a4bd5210SJason Evans /* Children are named. */ 754a4bd5210SJason Evans if (node->u.named.nchildren <= mib[i]) { 755a4bd5210SJason Evans ret = ENOENT; 756a4bd5210SJason Evans goto label_return; 757a4bd5210SJason Evans } 758a4bd5210SJason Evans node = &node->u.named.children[mib[i]]; 759a4bd5210SJason Evans } else { 760a4bd5210SJason Evans const ctl_node_t *inode; 761a4bd5210SJason Evans 762a4bd5210SJason Evans /* Indexed element. */ 763a4bd5210SJason Evans inode = &node->u.named.children[0]; 764a4bd5210SJason Evans node = inode->u.indexed.index(mib, miblen, mib[i]); 765a4bd5210SJason Evans if (node == NULL) { 766a4bd5210SJason Evans ret = ENOENT; 767a4bd5210SJason Evans goto label_return; 768a4bd5210SJason Evans } 769a4bd5210SJason Evans } 770a4bd5210SJason Evans } 771a4bd5210SJason Evans 772a4bd5210SJason Evans /* Call the ctl function. */ 773a4bd5210SJason Evans if (node->ctl == NULL) { 774a4bd5210SJason Evans /* Partial MIB. */ 775a4bd5210SJason Evans ret = ENOENT; 776a4bd5210SJason Evans goto label_return; 777a4bd5210SJason Evans } 778a4bd5210SJason Evans ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen); 779a4bd5210SJason Evans 780a4bd5210SJason Evans label_return: 781a4bd5210SJason Evans return(ret); 782a4bd5210SJason Evans } 783a4bd5210SJason Evans 784a4bd5210SJason Evans bool 785a4bd5210SJason Evans ctl_boot(void) 786a4bd5210SJason Evans { 787a4bd5210SJason Evans 788a4bd5210SJason Evans if (malloc_mutex_init(&ctl_mtx)) 789a4bd5210SJason Evans return (true); 790a4bd5210SJason Evans 791a4bd5210SJason Evans ctl_initialized = false; 792a4bd5210SJason Evans 793a4bd5210SJason Evans return (false); 794a4bd5210SJason Evans } 795a4bd5210SJason Evans 796a4bd5210SJason Evans /******************************************************************************/ 797a4bd5210SJason Evans /* *_ctl() functions. */ 798a4bd5210SJason Evans 799a4bd5210SJason Evans #define READONLY() do { \ 800a4bd5210SJason Evans if (newp != NULL || newlen != 0) { \ 801a4bd5210SJason Evans ret = EPERM; \ 802a4bd5210SJason Evans goto label_return; \ 803a4bd5210SJason Evans } \ 804a4bd5210SJason Evans } while (0) 805a4bd5210SJason Evans 806a4bd5210SJason Evans #define WRITEONLY() do { \ 807a4bd5210SJason Evans if (oldp != NULL || oldlenp != NULL) { \ 808a4bd5210SJason Evans ret = EPERM; \ 809a4bd5210SJason Evans goto label_return; \ 810a4bd5210SJason Evans } \ 811a4bd5210SJason Evans } while (0) 812a4bd5210SJason Evans 813a4bd5210SJason Evans #define VOID() do { \ 814a4bd5210SJason Evans READONLY(); \ 815a4bd5210SJason Evans WRITEONLY(); \ 816a4bd5210SJason Evans } while (0) 817a4bd5210SJason Evans 818a4bd5210SJason Evans #define READ(v, t) do { \ 819a4bd5210SJason Evans if (oldp != NULL && oldlenp != NULL) { \ 820a4bd5210SJason Evans if (*oldlenp != sizeof(t)) { \ 821a4bd5210SJason Evans size_t copylen = (sizeof(t) <= *oldlenp) \ 822a4bd5210SJason Evans ? sizeof(t) : *oldlenp; \ 823a4bd5210SJason Evans memcpy(oldp, (void *)&v, copylen); \ 824a4bd5210SJason Evans ret = EINVAL; \ 825a4bd5210SJason Evans goto label_return; \ 826a4bd5210SJason Evans } else \ 827a4bd5210SJason Evans *(t *)oldp = v; \ 828a4bd5210SJason Evans } \ 829a4bd5210SJason Evans } while (0) 830a4bd5210SJason Evans 831a4bd5210SJason Evans #define WRITE(v, t) do { \ 832a4bd5210SJason Evans if (newp != NULL) { \ 833a4bd5210SJason Evans if (newlen != sizeof(t)) { \ 834a4bd5210SJason Evans ret = EINVAL; \ 835a4bd5210SJason Evans goto label_return; \ 836a4bd5210SJason Evans } \ 837a4bd5210SJason Evans v = *(t *)newp; \ 838a4bd5210SJason Evans } \ 839a4bd5210SJason Evans } while (0) 840a4bd5210SJason Evans 841a4bd5210SJason Evans /* 842a4bd5210SJason Evans * There's a lot of code duplication in the following macros due to limitations 843a4bd5210SJason Evans * in how nested cpp macros are expanded. 844a4bd5210SJason Evans */ 845a4bd5210SJason Evans #define CTL_RO_CLGEN(c, l, n, v, t) \ 846a4bd5210SJason Evans static int \ 847a4bd5210SJason Evans n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ 848a4bd5210SJason Evans void *newp, size_t newlen) \ 849a4bd5210SJason Evans { \ 850a4bd5210SJason Evans int ret; \ 851a4bd5210SJason Evans t oldval; \ 852a4bd5210SJason Evans \ 853a4bd5210SJason Evans if ((c) == false) \ 854a4bd5210SJason Evans return (ENOENT); \ 855a4bd5210SJason Evans if (l) \ 856a4bd5210SJason Evans malloc_mutex_lock(&ctl_mtx); \ 857a4bd5210SJason Evans READONLY(); \ 858a4bd5210SJason Evans oldval = v; \ 859a4bd5210SJason Evans READ(oldval, t); \ 860a4bd5210SJason Evans \ 861a4bd5210SJason Evans ret = 0; \ 862a4bd5210SJason Evans label_return: \ 863a4bd5210SJason Evans if (l) \ 864a4bd5210SJason Evans malloc_mutex_unlock(&ctl_mtx); \ 865a4bd5210SJason Evans return (ret); \ 866a4bd5210SJason Evans } 867a4bd5210SJason Evans 868a4bd5210SJason Evans #define CTL_RO_CGEN(c, n, v, t) \ 869a4bd5210SJason Evans static int \ 870a4bd5210SJason Evans n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ 871a4bd5210SJason Evans void *newp, size_t newlen) \ 872a4bd5210SJason Evans { \ 873a4bd5210SJason Evans int ret; \ 874a4bd5210SJason Evans t oldval; \ 875a4bd5210SJason Evans \ 876a4bd5210SJason Evans if ((c) == false) \ 877a4bd5210SJason Evans return (ENOENT); \ 878a4bd5210SJason Evans malloc_mutex_lock(&ctl_mtx); \ 879a4bd5210SJason Evans READONLY(); \ 880a4bd5210SJason Evans oldval = v; \ 881a4bd5210SJason Evans READ(oldval, t); \ 882a4bd5210SJason Evans \ 883a4bd5210SJason Evans ret = 0; \ 884a4bd5210SJason Evans label_return: \ 885a4bd5210SJason Evans malloc_mutex_unlock(&ctl_mtx); \ 886a4bd5210SJason Evans return (ret); \ 887a4bd5210SJason Evans } 888a4bd5210SJason Evans 889a4bd5210SJason Evans #define CTL_RO_GEN(n, v, t) \ 890a4bd5210SJason Evans static int \ 891a4bd5210SJason Evans n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ 892a4bd5210SJason Evans void *newp, size_t newlen) \ 893a4bd5210SJason Evans { \ 894a4bd5210SJason Evans int ret; \ 895a4bd5210SJason Evans t oldval; \ 896a4bd5210SJason Evans \ 897a4bd5210SJason Evans malloc_mutex_lock(&ctl_mtx); \ 898a4bd5210SJason Evans READONLY(); \ 899a4bd5210SJason Evans oldval = v; \ 900a4bd5210SJason Evans READ(oldval, t); \ 901a4bd5210SJason Evans \ 902a4bd5210SJason Evans ret = 0; \ 903a4bd5210SJason Evans label_return: \ 904a4bd5210SJason Evans malloc_mutex_unlock(&ctl_mtx); \ 905a4bd5210SJason Evans return (ret); \ 906a4bd5210SJason Evans } 907a4bd5210SJason Evans 908a4bd5210SJason Evans /* 909a4bd5210SJason Evans * ctl_mtx is not acquired, under the assumption that no pertinent data will 910a4bd5210SJason Evans * mutate during the call. 911a4bd5210SJason Evans */ 912a4bd5210SJason Evans #define CTL_RO_NL_CGEN(c, n, v, t) \ 913a4bd5210SJason Evans static int \ 914a4bd5210SJason Evans n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ 915a4bd5210SJason Evans void *newp, size_t newlen) \ 916a4bd5210SJason Evans { \ 917a4bd5210SJason Evans int ret; \ 918a4bd5210SJason Evans t oldval; \ 919a4bd5210SJason Evans \ 920a4bd5210SJason Evans if ((c) == false) \ 921a4bd5210SJason Evans return (ENOENT); \ 922a4bd5210SJason Evans READONLY(); \ 923a4bd5210SJason Evans oldval = v; \ 924a4bd5210SJason Evans READ(oldval, t); \ 925a4bd5210SJason Evans \ 926a4bd5210SJason Evans ret = 0; \ 927a4bd5210SJason Evans label_return: \ 928a4bd5210SJason Evans return (ret); \ 929a4bd5210SJason Evans } 930a4bd5210SJason Evans 931a4bd5210SJason Evans #define CTL_RO_NL_GEN(n, v, t) \ 932a4bd5210SJason Evans static int \ 933a4bd5210SJason Evans n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ 934a4bd5210SJason Evans void *newp, size_t newlen) \ 935a4bd5210SJason Evans { \ 936a4bd5210SJason Evans int ret; \ 937a4bd5210SJason Evans t oldval; \ 938a4bd5210SJason Evans \ 939a4bd5210SJason Evans READONLY(); \ 940a4bd5210SJason Evans oldval = v; \ 941a4bd5210SJason Evans READ(oldval, t); \ 942a4bd5210SJason Evans \ 943a4bd5210SJason Evans ret = 0; \ 944a4bd5210SJason Evans label_return: \ 945a4bd5210SJason Evans return (ret); \ 946a4bd5210SJason Evans } 947a4bd5210SJason Evans 948a4bd5210SJason Evans #define CTL_RO_BOOL_CONFIG_GEN(n) \ 949a4bd5210SJason Evans static int \ 950a4bd5210SJason Evans n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \ 951a4bd5210SJason Evans void *newp, size_t newlen) \ 952a4bd5210SJason Evans { \ 953a4bd5210SJason Evans int ret; \ 954a4bd5210SJason Evans bool oldval; \ 955a4bd5210SJason Evans \ 956a4bd5210SJason Evans READONLY(); \ 957a4bd5210SJason Evans oldval = n; \ 958a4bd5210SJason Evans READ(oldval, bool); \ 959a4bd5210SJason Evans \ 960a4bd5210SJason Evans ret = 0; \ 961a4bd5210SJason Evans label_return: \ 962a4bd5210SJason Evans return (ret); \ 963a4bd5210SJason Evans } 964a4bd5210SJason Evans 965a4bd5210SJason Evans CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *) 966a4bd5210SJason Evans 967a4bd5210SJason Evans static int 968a4bd5210SJason Evans epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, 969a4bd5210SJason Evans void *newp, size_t newlen) 970a4bd5210SJason Evans { 971a4bd5210SJason Evans int ret; 972a4bd5210SJason Evans uint64_t newval; 973a4bd5210SJason Evans 974a4bd5210SJason Evans malloc_mutex_lock(&ctl_mtx); 975a4bd5210SJason Evans newval = 0; 976a4bd5210SJason Evans WRITE(newval, uint64_t); 977a4bd5210SJason Evans if (newval != 0) 978a4bd5210SJason Evans ctl_refresh(); 979a4bd5210SJason Evans READ(ctl_epoch, uint64_t); 980a4bd5210SJason Evans 981a4bd5210SJason Evans ret = 0; 982a4bd5210SJason Evans label_return: 983a4bd5210SJason Evans malloc_mutex_unlock(&ctl_mtx); 984a4bd5210SJason Evans return (ret); 985a4bd5210SJason Evans } 986a4bd5210SJason Evans 987a4bd5210SJason Evans static int 988a4bd5210SJason Evans thread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp, 989a4bd5210SJason Evans size_t *oldlenp, void *newp, size_t newlen) 990a4bd5210SJason Evans { 991a4bd5210SJason Evans int ret; 992a4bd5210SJason Evans bool oldval; 993a4bd5210SJason Evans 994a4bd5210SJason Evans if (config_tcache == false) 995a4bd5210SJason Evans return (ENOENT); 996a4bd5210SJason Evans 997a4bd5210SJason Evans oldval = tcache_enabled_get(); 998a4bd5210SJason Evans if (newp != NULL) { 999a4bd5210SJason Evans if (newlen != sizeof(bool)) { 1000a4bd5210SJason Evans ret = EINVAL; 1001a4bd5210SJason Evans goto label_return; 1002a4bd5210SJason Evans } 1003a4bd5210SJason Evans tcache_enabled_set(*(bool *)newp); 1004a4bd5210SJason Evans } 1005a4bd5210SJason Evans READ(oldval, bool); 1006a4bd5210SJason Evans 1007a4bd5210SJason Evans label_return: 1008a4bd5210SJason Evans ret = 0; 1009a4bd5210SJason Evans return (ret); 1010a4bd5210SJason Evans } 1011a4bd5210SJason Evans 1012a4bd5210SJason Evans static int 1013a4bd5210SJason Evans thread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp, 1014a4bd5210SJason Evans size_t *oldlenp, void *newp, size_t newlen) 1015a4bd5210SJason Evans { 1016a4bd5210SJason Evans int ret; 1017a4bd5210SJason Evans 1018a4bd5210SJason Evans if (config_tcache == false) 1019a4bd5210SJason Evans return (ENOENT); 1020a4bd5210SJason Evans 1021a4bd5210SJason Evans VOID(); 1022a4bd5210SJason Evans 1023a4bd5210SJason Evans tcache_flush(); 1024a4bd5210SJason Evans 1025a4bd5210SJason Evans ret = 0; 1026a4bd5210SJason Evans label_return: 1027a4bd5210SJason Evans return (ret); 1028a4bd5210SJason Evans } 1029a4bd5210SJason Evans 1030a4bd5210SJason Evans static int 1031a4bd5210SJason Evans thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, 1032a4bd5210SJason Evans void *newp, size_t newlen) 1033a4bd5210SJason Evans { 1034a4bd5210SJason Evans int ret; 1035a4bd5210SJason Evans unsigned newind, oldind; 1036a4bd5210SJason Evans 1037a4bd5210SJason Evans newind = oldind = choose_arena(NULL)->ind; 1038a4bd5210SJason Evans WRITE(newind, unsigned); 1039a4bd5210SJason Evans READ(oldind, unsigned); 1040a4bd5210SJason Evans if (newind != oldind) { 1041a4bd5210SJason Evans arena_t *arena; 1042a4bd5210SJason Evans 1043a4bd5210SJason Evans if (newind >= narenas) { 1044a4bd5210SJason Evans /* New arena index is out of range. */ 1045a4bd5210SJason Evans ret = EFAULT; 1046a4bd5210SJason Evans goto label_return; 1047a4bd5210SJason Evans } 1048a4bd5210SJason Evans 1049a4bd5210SJason Evans /* Initialize arena if necessary. */ 1050a4bd5210SJason Evans malloc_mutex_lock(&arenas_lock); 1051a4bd5210SJason Evans if ((arena = arenas[newind]) == NULL && (arena = 1052a4bd5210SJason Evans arenas_extend(newind)) == NULL) { 1053a4bd5210SJason Evans malloc_mutex_unlock(&arenas_lock); 1054a4bd5210SJason Evans ret = EAGAIN; 1055a4bd5210SJason Evans goto label_return; 1056a4bd5210SJason Evans } 1057a4bd5210SJason Evans assert(arena == arenas[newind]); 1058a4bd5210SJason Evans arenas[oldind]->nthreads--; 1059a4bd5210SJason Evans arenas[newind]->nthreads++; 1060a4bd5210SJason Evans malloc_mutex_unlock(&arenas_lock); 1061a4bd5210SJason Evans 1062a4bd5210SJason Evans /* Set new arena association. */ 1063a4bd5210SJason Evans if (config_tcache) { 1064a4bd5210SJason Evans tcache_t *tcache; 1065a4bd5210SJason Evans if ((uintptr_t)(tcache = *tcache_tsd_get()) > 1066a4bd5210SJason Evans (uintptr_t)TCACHE_STATE_MAX) { 1067a4bd5210SJason Evans tcache_arena_dissociate(tcache); 1068a4bd5210SJason Evans tcache_arena_associate(tcache, arena); 1069a4bd5210SJason Evans } 1070a4bd5210SJason Evans } 1071a4bd5210SJason Evans arenas_tsd_set(&arena); 1072a4bd5210SJason Evans } 1073a4bd5210SJason Evans 1074a4bd5210SJason Evans ret = 0; 1075a4bd5210SJason Evans label_return: 1076a4bd5210SJason Evans return (ret); 1077a4bd5210SJason Evans } 1078a4bd5210SJason Evans 1079a4bd5210SJason Evans CTL_RO_NL_CGEN(config_stats, thread_allocated, 1080a4bd5210SJason Evans thread_allocated_tsd_get()->allocated, uint64_t) 1081a4bd5210SJason Evans CTL_RO_NL_CGEN(config_stats, thread_allocatedp, 1082a4bd5210SJason Evans &thread_allocated_tsd_get()->allocated, uint64_t *) 1083a4bd5210SJason Evans CTL_RO_NL_CGEN(config_stats, thread_deallocated, 1084a4bd5210SJason Evans thread_allocated_tsd_get()->deallocated, uint64_t) 1085a4bd5210SJason Evans CTL_RO_NL_CGEN(config_stats, thread_deallocatedp, 1086a4bd5210SJason Evans &thread_allocated_tsd_get()->deallocated, uint64_t *) 1087a4bd5210SJason Evans 1088a4bd5210SJason Evans /******************************************************************************/ 1089a4bd5210SJason Evans 1090a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_debug) 1091a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_dss) 1092a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_fill) 1093a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_lazy_lock) 1094a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_munmap) 1095a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_prof) 1096a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc) 1097a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind) 1098a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_stats) 1099a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_tcache) 1100a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_tls) 1101a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_utrace) 1102a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_valgrind) 1103a4bd5210SJason Evans CTL_RO_BOOL_CONFIG_GEN(config_xmalloc) 1104a4bd5210SJason Evans 1105a4bd5210SJason Evans /******************************************************************************/ 1106a4bd5210SJason Evans 1107a4bd5210SJason Evans CTL_RO_NL_GEN(opt_abort, opt_abort, bool) 1108a4bd5210SJason Evans CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t) 1109a4bd5210SJason Evans CTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t) 1110a4bd5210SJason Evans CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t) 1111a4bd5210SJason Evans CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool) 1112a4bd5210SJason Evans CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool) 1113a4bd5210SJason Evans CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool) 1114a4bd5210SJason Evans CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t) 1115a4bd5210SJason Evans CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool) 1116a4bd5210SJason Evans CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool) 1117a4bd5210SJason Evans CTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool) 1118a4bd5210SJason Evans CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool) 1119a4bd5210SJason Evans CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool) 1120a4bd5210SJason Evans CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t) 1121a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool) 1122a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *) 1123a4bd5210SJason Evans CTL_RO_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) /* Mutable. */ 1124a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t) 1125a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t) 1126a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool) 1127*8ed34ab0SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool) 1128a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool) 1129a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool) 1130a4bd5210SJason Evans 1131a4bd5210SJason Evans /******************************************************************************/ 1132a4bd5210SJason Evans 1133a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t) 1134a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t) 1135a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t) 1136a4bd5210SJason Evans const ctl_node_t * 1137a4bd5210SJason Evans arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i) 1138a4bd5210SJason Evans { 1139a4bd5210SJason Evans 1140a4bd5210SJason Evans if (i > NBINS) 1141a4bd5210SJason Evans return (NULL); 1142a4bd5210SJason Evans return (super_arenas_bin_i_node); 1143a4bd5210SJason Evans } 1144a4bd5210SJason Evans 1145a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t) 1146a4bd5210SJason Evans const ctl_node_t * 1147a4bd5210SJason Evans arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i) 1148a4bd5210SJason Evans { 1149a4bd5210SJason Evans 1150a4bd5210SJason Evans if (i > nlclasses) 1151a4bd5210SJason Evans return (NULL); 1152a4bd5210SJason Evans return (super_arenas_lrun_i_node); 1153a4bd5210SJason Evans } 1154a4bd5210SJason Evans 1155a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_narenas, narenas, unsigned) 1156a4bd5210SJason Evans 1157a4bd5210SJason Evans static int 1158a4bd5210SJason Evans arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp, 1159a4bd5210SJason Evans size_t *oldlenp, void *newp, size_t newlen) 1160a4bd5210SJason Evans { 1161a4bd5210SJason Evans int ret; 1162a4bd5210SJason Evans unsigned nread, i; 1163a4bd5210SJason Evans 1164a4bd5210SJason Evans malloc_mutex_lock(&ctl_mtx); 1165a4bd5210SJason Evans READONLY(); 1166a4bd5210SJason Evans if (*oldlenp != narenas * sizeof(bool)) { 1167a4bd5210SJason Evans ret = EINVAL; 1168a4bd5210SJason Evans nread = (*oldlenp < narenas * sizeof(bool)) 1169a4bd5210SJason Evans ? (*oldlenp / sizeof(bool)) : narenas; 1170a4bd5210SJason Evans } else { 1171a4bd5210SJason Evans ret = 0; 1172a4bd5210SJason Evans nread = narenas; 1173a4bd5210SJason Evans } 1174a4bd5210SJason Evans 1175a4bd5210SJason Evans for (i = 0; i < nread; i++) 1176a4bd5210SJason Evans ((bool *)oldp)[i] = ctl_stats.arenas[i].initialized; 1177a4bd5210SJason Evans 1178a4bd5210SJason Evans label_return: 1179a4bd5210SJason Evans malloc_mutex_unlock(&ctl_mtx); 1180a4bd5210SJason Evans return (ret); 1181a4bd5210SJason Evans } 1182a4bd5210SJason Evans 1183a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t) 1184a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_page, PAGE, size_t) 1185a4bd5210SJason Evans CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t) 1186a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned) 1187a4bd5210SJason Evans CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned) 1188a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t) 1189a4bd5210SJason Evans 1190a4bd5210SJason Evans static int 1191a4bd5210SJason Evans arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, 1192a4bd5210SJason Evans void *newp, size_t newlen) 1193a4bd5210SJason Evans { 1194a4bd5210SJason Evans int ret; 1195a4bd5210SJason Evans unsigned arena; 1196a4bd5210SJason Evans 1197a4bd5210SJason Evans WRITEONLY(); 1198a4bd5210SJason Evans arena = UINT_MAX; 1199a4bd5210SJason Evans WRITE(arena, unsigned); 1200a4bd5210SJason Evans if (newp != NULL && arena >= narenas) { 1201a4bd5210SJason Evans ret = EFAULT; 1202a4bd5210SJason Evans goto label_return; 1203a4bd5210SJason Evans } else { 1204a4bd5210SJason Evans arena_t *tarenas[narenas]; 1205a4bd5210SJason Evans 1206a4bd5210SJason Evans malloc_mutex_lock(&arenas_lock); 1207a4bd5210SJason Evans memcpy(tarenas, arenas, sizeof(arena_t *) * narenas); 1208a4bd5210SJason Evans malloc_mutex_unlock(&arenas_lock); 1209a4bd5210SJason Evans 1210a4bd5210SJason Evans if (arena == UINT_MAX) { 1211a4bd5210SJason Evans unsigned i; 1212a4bd5210SJason Evans for (i = 0; i < narenas; i++) { 1213a4bd5210SJason Evans if (tarenas[i] != NULL) 1214a4bd5210SJason Evans arena_purge_all(tarenas[i]); 1215a4bd5210SJason Evans } 1216a4bd5210SJason Evans } else { 1217a4bd5210SJason Evans assert(arena < narenas); 1218a4bd5210SJason Evans if (tarenas[arena] != NULL) 1219a4bd5210SJason Evans arena_purge_all(tarenas[arena]); 1220a4bd5210SJason Evans } 1221a4bd5210SJason Evans } 1222a4bd5210SJason Evans 1223a4bd5210SJason Evans ret = 0; 1224a4bd5210SJason Evans label_return: 1225a4bd5210SJason Evans return (ret); 1226a4bd5210SJason Evans } 1227a4bd5210SJason Evans 1228a4bd5210SJason Evans /******************************************************************************/ 1229a4bd5210SJason Evans 1230a4bd5210SJason Evans static int 1231a4bd5210SJason Evans prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, 1232a4bd5210SJason Evans void *newp, size_t newlen) 1233a4bd5210SJason Evans { 1234a4bd5210SJason Evans int ret; 1235a4bd5210SJason Evans bool oldval; 1236a4bd5210SJason Evans 1237a4bd5210SJason Evans if (config_prof == false) 1238a4bd5210SJason Evans return (ENOENT); 1239a4bd5210SJason Evans 1240a4bd5210SJason Evans malloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */ 1241a4bd5210SJason Evans oldval = opt_prof_active; 1242a4bd5210SJason Evans if (newp != NULL) { 1243a4bd5210SJason Evans /* 1244a4bd5210SJason Evans * The memory barriers will tend to make opt_prof_active 1245a4bd5210SJason Evans * propagate faster on systems with weak memory ordering. 1246a4bd5210SJason Evans */ 1247a4bd5210SJason Evans mb_write(); 1248a4bd5210SJason Evans WRITE(opt_prof_active, bool); 1249a4bd5210SJason Evans mb_write(); 1250a4bd5210SJason Evans } 1251a4bd5210SJason Evans READ(oldval, bool); 1252a4bd5210SJason Evans 1253a4bd5210SJason Evans ret = 0; 1254a4bd5210SJason Evans label_return: 1255a4bd5210SJason Evans malloc_mutex_unlock(&ctl_mtx); 1256a4bd5210SJason Evans return (ret); 1257a4bd5210SJason Evans } 1258a4bd5210SJason Evans 1259a4bd5210SJason Evans static int 1260a4bd5210SJason Evans prof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, 1261a4bd5210SJason Evans void *newp, size_t newlen) 1262a4bd5210SJason Evans { 1263a4bd5210SJason Evans int ret; 1264a4bd5210SJason Evans const char *filename = NULL; 1265a4bd5210SJason Evans 1266a4bd5210SJason Evans if (config_prof == false) 1267a4bd5210SJason Evans return (ENOENT); 1268a4bd5210SJason Evans 1269a4bd5210SJason Evans WRITEONLY(); 1270a4bd5210SJason Evans WRITE(filename, const char *); 1271a4bd5210SJason Evans 1272a4bd5210SJason Evans if (prof_mdump(filename)) { 1273a4bd5210SJason Evans ret = EFAULT; 1274a4bd5210SJason Evans goto label_return; 1275a4bd5210SJason Evans } 1276a4bd5210SJason Evans 1277a4bd5210SJason Evans ret = 0; 1278a4bd5210SJason Evans label_return: 1279a4bd5210SJason Evans return (ret); 1280a4bd5210SJason Evans } 1281a4bd5210SJason Evans 1282a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t) 1283a4bd5210SJason Evans 1284a4bd5210SJason Evans /******************************************************************************/ 1285a4bd5210SJason Evans 1286a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current, 1287a4bd5210SJason Evans size_t) 1288a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t) 1289a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t) 1290a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t) 1291a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t) 1292a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t) 1293a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated, 1294a4bd5210SJason Evans ctl_stats.arenas[mib[2]].allocated_small, size_t) 1295a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc, 1296a4bd5210SJason Evans ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t) 1297a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc, 1298a4bd5210SJason Evans ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t) 1299a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests, 1300a4bd5210SJason Evans ctl_stats.arenas[mib[2]].nrequests_small, uint64_t) 1301a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated, 1302a4bd5210SJason Evans ctl_stats.arenas[mib[2]].astats.allocated_large, size_t) 1303a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc, 1304a4bd5210SJason Evans ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t) 1305a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc, 1306a4bd5210SJason Evans ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t) 1307a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests, 1308a4bd5210SJason Evans ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t) 1309a4bd5210SJason Evans 1310a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated, 1311a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t) 1312a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc, 1313a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t) 1314a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc, 1315a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t) 1316a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests, 1317a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t) 1318a4bd5210SJason Evans CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills, 1319a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t) 1320a4bd5210SJason Evans CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes, 1321a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t) 1322a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns, 1323a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t) 1324a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns, 1325a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t) 1326a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns, 1327a4bd5210SJason Evans ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t) 1328a4bd5210SJason Evans 1329a4bd5210SJason Evans const ctl_node_t * 1330a4bd5210SJason Evans stats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j) 1331a4bd5210SJason Evans { 1332a4bd5210SJason Evans 1333a4bd5210SJason Evans if (j > NBINS) 1334a4bd5210SJason Evans return (NULL); 1335a4bd5210SJason Evans return (super_stats_arenas_i_bins_j_node); 1336a4bd5210SJason Evans } 1337a4bd5210SJason Evans 1338a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc, 1339a4bd5210SJason Evans ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t) 1340a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc, 1341a4bd5210SJason Evans ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t) 1342a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests, 1343a4bd5210SJason Evans ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t) 1344a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns, 1345a4bd5210SJason Evans ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t) 1346a4bd5210SJason Evans 1347a4bd5210SJason Evans const ctl_node_t * 1348a4bd5210SJason Evans stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j) 1349a4bd5210SJason Evans { 1350a4bd5210SJason Evans 1351a4bd5210SJason Evans if (j > nlclasses) 1352a4bd5210SJason Evans return (NULL); 1353a4bd5210SJason Evans return (super_stats_arenas_i_lruns_j_node); 1354a4bd5210SJason Evans } 1355a4bd5210SJason Evans 1356a4bd5210SJason Evans CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned) 1357a4bd5210SJason Evans CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t) 1358a4bd5210SJason Evans CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t) 1359a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_mapped, 1360a4bd5210SJason Evans ctl_stats.arenas[mib[2]].astats.mapped, size_t) 1361a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_npurge, 1362a4bd5210SJason Evans ctl_stats.arenas[mib[2]].astats.npurge, uint64_t) 1363a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise, 1364a4bd5210SJason Evans ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t) 1365a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_purged, 1366a4bd5210SJason Evans ctl_stats.arenas[mib[2]].astats.purged, uint64_t) 1367a4bd5210SJason Evans 1368a4bd5210SJason Evans const ctl_node_t * 1369a4bd5210SJason Evans stats_arenas_i_index(const size_t *mib, size_t miblen, size_t i) 1370a4bd5210SJason Evans { 1371a4bd5210SJason Evans const ctl_node_t * ret; 1372a4bd5210SJason Evans 1373a4bd5210SJason Evans malloc_mutex_lock(&ctl_mtx); 1374a4bd5210SJason Evans if (ctl_stats.arenas[i].initialized == false) { 1375a4bd5210SJason Evans ret = NULL; 1376a4bd5210SJason Evans goto label_return; 1377a4bd5210SJason Evans } 1378a4bd5210SJason Evans 1379a4bd5210SJason Evans ret = super_stats_arenas_i_node; 1380a4bd5210SJason Evans label_return: 1381a4bd5210SJason Evans malloc_mutex_unlock(&ctl_mtx); 1382a4bd5210SJason Evans return (ret); 1383a4bd5210SJason Evans } 1384a4bd5210SJason Evans 1385a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *) 1386a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t) 1387a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t) 1388a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t) 1389