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