blob: dddf3beeb57ece0e5c98101f74675095f885443d [file] [log] [blame]
Jason Evans3c234352010-01-27 13:10:55 -08001#define JEMALLOC_CTL_C_
Jason Evans376b1522010-02-11 14:45:59 -08002#include "jemalloc/internal/jemalloc_internal.h"
Jason Evans3c234352010-01-27 13:10:55 -08003
4/******************************************************************************/
5/* Data. */
6
Jason Evansfc4dcfa2010-11-24 15:44:21 -08007/*
8 * ctl_mtx protects the following:
9 * - ctl_stats.*
10 * - opt_prof_active
Jason Evansfc4dcfa2010-11-24 15:44:21 -080011 */
Jason Evans3c234352010-01-27 13:10:55 -080012static malloc_mutex_t ctl_mtx;
13static bool ctl_initialized;
14static uint64_t ctl_epoch;
15static ctl_stats_t ctl_stats;
16
17/******************************************************************************/
Mike Hommey461ad5c2012-04-20 08:38:42 +020018/* Helpers for named and indexed nodes. */
19
20static inline const ctl_named_node_t *
21ctl_named_node(const ctl_node_t *node)
22{
23
24 return ((node->named) ? (const ctl_named_node_t *)node : NULL);
25}
26
27static inline const ctl_named_node_t *
28ctl_named_children(const ctl_named_node_t *node, int index)
29{
30 const ctl_named_node_t *children = ctl_named_node(node->children);
31
32 return (children ? &children[index] : NULL);
33}
34
35static inline const ctl_indexed_node_t *
36ctl_indexed_node(const ctl_node_t *node)
37{
38
39 return ((node->named == false) ? (const ctl_indexed_node_t *)node :
40 NULL);
41}
42
43/******************************************************************************/
Jason Evans3c234352010-01-27 13:10:55 -080044/* Function prototypes for non-inline static functions. */
45
46#define CTL_PROTO(n) \
47static int n##_ctl(const size_t *mib, size_t miblen, void *oldp, \
48 size_t *oldlenp, void *newp, size_t newlen);
49
50#define INDEX_PROTO(n) \
Mike Hommey461ad5c2012-04-20 08:38:42 +020051const ctl_named_node_t *n##_index(const size_t *mib, size_t miblen, \
Jason Evans3c234352010-01-27 13:10:55 -080052 size_t i);
53
Jason Evans3c234352010-01-27 13:10:55 -080054static bool ctl_arena_init(ctl_arena_stats_t *astats);
Jason Evans3c234352010-01-27 13:10:55 -080055static void ctl_arena_clear(ctl_arena_stats_t *astats);
Jason Evans86815df2010-03-13 20:32:56 -080056static void ctl_arena_stats_amerge(ctl_arena_stats_t *cstats,
57 arena_t *arena);
58static void ctl_arena_stats_smerge(ctl_arena_stats_t *sstats,
59 ctl_arena_stats_t *astats);
Jason Evans3c234352010-01-27 13:10:55 -080060static void ctl_arena_refresh(arena_t *arena, unsigned i);
61static void ctl_refresh(void);
62static bool ctl_init(void);
63static int ctl_lookup(const char *name, ctl_node_t const **nodesp,
64 size_t *mibp, size_t *depthp);
65
Jason Evansa40bc7a2010-03-02 13:01:16 -080066CTL_PROTO(version)
Jason Evans3c234352010-01-27 13:10:55 -080067CTL_PROTO(epoch)
Jason Evansd4be8b72012-03-26 18:54:44 -070068CTL_PROTO(thread_tcache_enabled)
Jason Evanse7b8fa12012-03-16 17:09:32 -070069CTL_PROTO(thread_tcache_flush)
Jason Evansb267d0f2010-08-13 15:42:29 -070070CTL_PROTO(thread_arena)
Jason Evans93443682010-10-20 17:39:18 -070071CTL_PROTO(thread_allocated)
Jason Evansecf229a2010-12-03 15:55:47 -080072CTL_PROTO(thread_allocatedp)
Jason Evans93443682010-10-20 17:39:18 -070073CTL_PROTO(thread_deallocated)
Jason Evansecf229a2010-12-03 15:55:47 -080074CTL_PROTO(thread_deallocatedp)
Jason Evans3c234352010-01-27 13:10:55 -080075CTL_PROTO(config_debug)
76CTL_PROTO(config_dss)
Jason Evans3c234352010-01-27 13:10:55 -080077CTL_PROTO(config_fill)
78CTL_PROTO(config_lazy_lock)
Jason Evans59ae2762012-04-16 17:52:27 -070079CTL_PROTO(config_munmap)
Jason Evansd34f9e72010-02-11 13:19:21 -080080CTL_PROTO(config_prof)
81CTL_PROTO(config_prof_libgcc)
82CTL_PROTO(config_prof_libunwind)
Jason Evans3c234352010-01-27 13:10:55 -080083CTL_PROTO(config_stats)
Jason Evans3c234352010-01-27 13:10:55 -080084CTL_PROTO(config_tcache)
Jason Evans3c234352010-01-27 13:10:55 -080085CTL_PROTO(config_tls)
Jason Evansb1476112012-04-05 13:36:17 -070086CTL_PROTO(config_utrace)
Jason Evans122449b2012-04-06 00:35:09 -070087CTL_PROTO(config_valgrind)
Jason Evans3c234352010-01-27 13:10:55 -080088CTL_PROTO(config_xmalloc)
89CTL_PROTO(opt_abort)
Jason Evanse7339702010-10-23 18:37:06 -070090CTL_PROTO(opt_lg_chunk)
91CTL_PROTO(opt_narenas)
92CTL_PROTO(opt_lg_dirty_mult)
93CTL_PROTO(opt_stats_print)
Jason Evans3c234352010-01-27 13:10:55 -080094CTL_PROTO(opt_junk)
Jason Evanse7339702010-10-23 18:37:06 -070095CTL_PROTO(opt_zero)
Jason Evans122449b2012-04-06 00:35:09 -070096CTL_PROTO(opt_quarantine)
97CTL_PROTO(opt_redzone)
Jason Evansb1476112012-04-05 13:36:17 -070098CTL_PROTO(opt_utrace)
Jason Evans122449b2012-04-06 00:35:09 -070099CTL_PROTO(opt_valgrind)
Jason Evans3c234352010-01-27 13:10:55 -0800100CTL_PROTO(opt_xmalloc)
Jason Evans3fa9a2f2010-03-07 15:34:14 -0800101CTL_PROTO(opt_tcache)
Jason Evansf3ca7c82012-04-04 16:16:09 -0700102CTL_PROTO(opt_lg_tcache_max)
Jason Evansd34f9e72010-02-11 13:19:21 -0800103CTL_PROTO(opt_prof)
Jason Evanse7339702010-10-23 18:37:06 -0700104CTL_PROTO(opt_prof_prefix)
Jason Evansf18c9822010-03-31 18:43:24 -0700105CTL_PROTO(opt_prof_active)
Jason Evansb9477e72010-03-01 20:15:26 -0800106CTL_PROTO(opt_lg_prof_sample)
Jason Evansd34f9e72010-02-11 13:19:21 -0800107CTL_PROTO(opt_lg_prof_interval)
Jason Evanse7339702010-10-23 18:37:06 -0700108CTL_PROTO(opt_prof_gdump)
Jason Evans0b25fe72012-04-17 16:39:33 -0700109CTL_PROTO(opt_prof_final)
Jason Evansd34f9e72010-02-11 13:19:21 -0800110CTL_PROTO(opt_prof_leak)
Jason Evansa881cd22010-10-02 15:18:50 -0700111CTL_PROTO(opt_prof_accum)
Jason Evans3c234352010-01-27 13:10:55 -0800112CTL_PROTO(arenas_bin_i_size)
113CTL_PROTO(arenas_bin_i_nregs)
114CTL_PROTO(arenas_bin_i_run_size)
115INDEX_PROTO(arenas_bin_i)
116CTL_PROTO(arenas_lrun_i_size)
117INDEX_PROTO(arenas_lrun_i)
118CTL_PROTO(arenas_narenas)
119CTL_PROTO(arenas_initialized)
120CTL_PROTO(arenas_quantum)
Jason Evansae4c7b42012-04-02 07:04:34 -0700121CTL_PROTO(arenas_page)
Jason Evansdafde142010-03-17 16:27:39 -0700122CTL_PROTO(arenas_tcache_max)
Jason Evans3c234352010-01-27 13:10:55 -0800123CTL_PROTO(arenas_nbins)
Jason Evansdafde142010-03-17 16:27:39 -0700124CTL_PROTO(arenas_nhbins)
Jason Evans3c234352010-01-27 13:10:55 -0800125CTL_PROTO(arenas_nlruns)
Jason Evans6005f072010-09-30 16:55:08 -0700126CTL_PROTO(arenas_purge)
Jason Evansf18c9822010-03-31 18:43:24 -0700127CTL_PROTO(prof_active)
Jason Evansd34f9e72010-02-11 13:19:21 -0800128CTL_PROTO(prof_dump)
129CTL_PROTO(prof_interval)
Jason Evans3c234352010-01-27 13:10:55 -0800130CTL_PROTO(stats_chunks_current)
131CTL_PROTO(stats_chunks_total)
132CTL_PROTO(stats_chunks_high)
133CTL_PROTO(stats_huge_allocated)
134CTL_PROTO(stats_huge_nmalloc)
135CTL_PROTO(stats_huge_ndalloc)
136CTL_PROTO(stats_arenas_i_small_allocated)
137CTL_PROTO(stats_arenas_i_small_nmalloc)
138CTL_PROTO(stats_arenas_i_small_ndalloc)
Jason Evans86815df2010-03-13 20:32:56 -0800139CTL_PROTO(stats_arenas_i_small_nrequests)
Jason Evans3c234352010-01-27 13:10:55 -0800140CTL_PROTO(stats_arenas_i_large_allocated)
141CTL_PROTO(stats_arenas_i_large_nmalloc)
142CTL_PROTO(stats_arenas_i_large_ndalloc)
Jason Evansdafde142010-03-17 16:27:39 -0700143CTL_PROTO(stats_arenas_i_large_nrequests)
Jason Evans86815df2010-03-13 20:32:56 -0800144CTL_PROTO(stats_arenas_i_bins_j_allocated)
145CTL_PROTO(stats_arenas_i_bins_j_nmalloc)
146CTL_PROTO(stats_arenas_i_bins_j_ndalloc)
Jason Evans3c234352010-01-27 13:10:55 -0800147CTL_PROTO(stats_arenas_i_bins_j_nrequests)
Jason Evans3c234352010-01-27 13:10:55 -0800148CTL_PROTO(stats_arenas_i_bins_j_nfills)
149CTL_PROTO(stats_arenas_i_bins_j_nflushes)
Jason Evans3c234352010-01-27 13:10:55 -0800150CTL_PROTO(stats_arenas_i_bins_j_nruns)
151CTL_PROTO(stats_arenas_i_bins_j_nreruns)
Jason Evans3c234352010-01-27 13:10:55 -0800152CTL_PROTO(stats_arenas_i_bins_j_curruns)
153INDEX_PROTO(stats_arenas_i_bins_j)
Jason Evansdafde142010-03-17 16:27:39 -0700154CTL_PROTO(stats_arenas_i_lruns_j_nmalloc)
155CTL_PROTO(stats_arenas_i_lruns_j_ndalloc)
Jason Evans3c234352010-01-27 13:10:55 -0800156CTL_PROTO(stats_arenas_i_lruns_j_nrequests)
Jason Evans3c234352010-01-27 13:10:55 -0800157CTL_PROTO(stats_arenas_i_lruns_j_curruns)
158INDEX_PROTO(stats_arenas_i_lruns_j)
Jason Evans597632b2011-03-18 13:41:33 -0700159CTL_PROTO(stats_arenas_i_nthreads)
Jason Evans3c234352010-01-27 13:10:55 -0800160CTL_PROTO(stats_arenas_i_pactive)
161CTL_PROTO(stats_arenas_i_pdirty)
Jason Evans3c234352010-01-27 13:10:55 -0800162CTL_PROTO(stats_arenas_i_mapped)
163CTL_PROTO(stats_arenas_i_npurge)
164CTL_PROTO(stats_arenas_i_nmadvise)
165CTL_PROTO(stats_arenas_i_purged)
Jason Evans3c234352010-01-27 13:10:55 -0800166INDEX_PROTO(stats_arenas_i)
Jason Evans0657f122011-03-18 17:56:14 -0700167CTL_PROTO(stats_cactive)
Jason Evans3c234352010-01-27 13:10:55 -0800168CTL_PROTO(stats_allocated)
169CTL_PROTO(stats_active)
170CTL_PROTO(stats_mapped)
Jason Evans3c234352010-01-27 13:10:55 -0800171
172/******************************************************************************/
173/* mallctl tree. */
174
175/* Maximum tree depth. */
176#define CTL_MAX_DEPTH 6
177
Mike Hommey461ad5c2012-04-20 08:38:42 +0200178#define NAME(n) {true}, n
Jason Evans65f343a2012-04-23 19:31:45 -0700179#define CHILD(t, c) \
180 sizeof(c##_node) / sizeof(ctl_##t##_node_t), \
181 (ctl_node_t *)c##_node, \
182 NULL
Mike Hommey461ad5c2012-04-20 08:38:42 +0200183#define CTL(c) 0, NULL, c##_ctl
Jason Evans3c234352010-01-27 13:10:55 -0800184
185/*
186 * Only handles internal indexed nodes, since there are currently no external
187 * ones.
188 */
Mike Hommey461ad5c2012-04-20 08:38:42 +0200189#define INDEX(i) {false}, i##_index
Jason Evans3c234352010-01-27 13:10:55 -0800190
Mike Hommey461ad5c2012-04-20 08:38:42 +0200191static const ctl_named_node_t tcache_node[] = {
Jason Evansd4be8b72012-03-26 18:54:44 -0700192 {NAME("enabled"), CTL(thread_tcache_enabled)},
Jason Evanse7b8fa12012-03-16 17:09:32 -0700193 {NAME("flush"), CTL(thread_tcache_flush)}
Jason Evans3c234352010-01-27 13:10:55 -0800194};
Jason Evans3c234352010-01-27 13:10:55 -0800195
Mike Hommey461ad5c2012-04-20 08:38:42 +0200196static const ctl_named_node_t thread_node[] = {
Jason Evans7372b152012-02-10 20:22:09 -0800197 {NAME("arena"), CTL(thread_arena)},
Jason Evans93443682010-10-20 17:39:18 -0700198 {NAME("allocated"), CTL(thread_allocated)},
Jason Evansecf229a2010-12-03 15:55:47 -0800199 {NAME("allocatedp"), CTL(thread_allocatedp)},
200 {NAME("deallocated"), CTL(thread_deallocated)},
Jason Evanse7b8fa12012-03-16 17:09:32 -0700201 {NAME("deallocatedp"), CTL(thread_deallocatedp)},
Jason Evans65f343a2012-04-23 19:31:45 -0700202 {NAME("tcache"), CHILD(named, tcache)}
Jason Evansb267d0f2010-08-13 15:42:29 -0700203};
Jason Evansb267d0f2010-08-13 15:42:29 -0700204
Mike Hommey461ad5c2012-04-20 08:38:42 +0200205static const ctl_named_node_t config_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800206 {NAME("debug"), CTL(config_debug)},
207 {NAME("dss"), CTL(config_dss)},
Jason Evans3c234352010-01-27 13:10:55 -0800208 {NAME("fill"), CTL(config_fill)},
209 {NAME("lazy_lock"), CTL(config_lazy_lock)},
Jason Evans59ae2762012-04-16 17:52:27 -0700210 {NAME("munmap"), CTL(config_munmap)},
Jason Evansd34f9e72010-02-11 13:19:21 -0800211 {NAME("prof"), CTL(config_prof)},
212 {NAME("prof_libgcc"), CTL(config_prof_libgcc)},
213 {NAME("prof_libunwind"), CTL(config_prof_libunwind)},
Jason Evans3c234352010-01-27 13:10:55 -0800214 {NAME("stats"), CTL(config_stats)},
Jason Evans3c234352010-01-27 13:10:55 -0800215 {NAME("tcache"), CTL(config_tcache)},
Jason Evans3c234352010-01-27 13:10:55 -0800216 {NAME("tls"), CTL(config_tls)},
Jason Evansb1476112012-04-05 13:36:17 -0700217 {NAME("utrace"), CTL(config_utrace)},
Jason Evans122449b2012-04-06 00:35:09 -0700218 {NAME("valgrind"), CTL(config_valgrind)},
Jason Evans3c234352010-01-27 13:10:55 -0800219 {NAME("xmalloc"), CTL(config_xmalloc)}
220};
221
Mike Hommey461ad5c2012-04-20 08:38:42 +0200222static const ctl_named_node_t opt_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800223 {NAME("abort"), CTL(opt_abort)},
Jason Evanse7339702010-10-23 18:37:06 -0700224 {NAME("lg_chunk"), CTL(opt_lg_chunk)},
225 {NAME("narenas"), CTL(opt_narenas)},
226 {NAME("lg_dirty_mult"), CTL(opt_lg_dirty_mult)},
Jason Evans7372b152012-02-10 20:22:09 -0800227 {NAME("stats_print"), CTL(opt_stats_print)},
Jason Evans3c234352010-01-27 13:10:55 -0800228 {NAME("junk"), CTL(opt_junk)},
Jason Evans7372b152012-02-10 20:22:09 -0800229 {NAME("zero"), CTL(opt_zero)},
Jason Evans122449b2012-04-06 00:35:09 -0700230 {NAME("quarantine"), CTL(opt_quarantine)},
231 {NAME("redzone"), CTL(opt_redzone)},
Jason Evansb1476112012-04-05 13:36:17 -0700232 {NAME("utrace"), CTL(opt_utrace)},
Jason Evans122449b2012-04-06 00:35:09 -0700233 {NAME("valgrind"), CTL(opt_valgrind)},
Jason Evans7372b152012-02-10 20:22:09 -0800234 {NAME("xmalloc"), CTL(opt_xmalloc)},
Jason Evans3fa9a2f2010-03-07 15:34:14 -0800235 {NAME("tcache"), CTL(opt_tcache)},
Jason Evansf3ca7c82012-04-04 16:16:09 -0700236 {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)},
Jason Evansd34f9e72010-02-11 13:19:21 -0800237 {NAME("prof"), CTL(opt_prof)},
Jason Evanse7339702010-10-23 18:37:06 -0700238 {NAME("prof_prefix"), CTL(opt_prof_prefix)},
Jason Evansf18c9822010-03-31 18:43:24 -0700239 {NAME("prof_active"), CTL(opt_prof_active)},
Jason Evansb9477e72010-03-01 20:15:26 -0800240 {NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
Jason Evansd34f9e72010-02-11 13:19:21 -0800241 {NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
Jason Evanse7339702010-10-23 18:37:06 -0700242 {NAME("prof_gdump"), CTL(opt_prof_gdump)},
Jason Evans0b25fe72012-04-17 16:39:33 -0700243 {NAME("prof_final"), CTL(opt_prof_final)},
Jason Evansd34f9e72010-02-11 13:19:21 -0800244 {NAME("prof_leak"), CTL(opt_prof_leak)},
Jason Evans0b526ff2012-02-13 18:04:26 -0800245 {NAME("prof_accum"), CTL(opt_prof_accum)}
Jason Evans3c234352010-01-27 13:10:55 -0800246};
247
Mike Hommey461ad5c2012-04-20 08:38:42 +0200248static const ctl_named_node_t arenas_bin_i_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800249 {NAME("size"), CTL(arenas_bin_i_size)},
250 {NAME("nregs"), CTL(arenas_bin_i_nregs)},
251 {NAME("run_size"), CTL(arenas_bin_i_run_size)}
252};
Mike Hommey461ad5c2012-04-20 08:38:42 +0200253static const ctl_named_node_t super_arenas_bin_i_node[] = {
Jason Evans65f343a2012-04-23 19:31:45 -0700254 {NAME(""), CHILD(named, arenas_bin_i)}
Jason Evans3c234352010-01-27 13:10:55 -0800255};
256
Mike Hommey461ad5c2012-04-20 08:38:42 +0200257static const ctl_indexed_node_t arenas_bin_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800258 {INDEX(arenas_bin_i)}
259};
260
Mike Hommey461ad5c2012-04-20 08:38:42 +0200261static const ctl_named_node_t arenas_lrun_i_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800262 {NAME("size"), CTL(arenas_lrun_i_size)}
263};
Mike Hommey461ad5c2012-04-20 08:38:42 +0200264static const ctl_named_node_t super_arenas_lrun_i_node[] = {
Jason Evans65f343a2012-04-23 19:31:45 -0700265 {NAME(""), CHILD(named, arenas_lrun_i)}
Jason Evans3c234352010-01-27 13:10:55 -0800266};
267
Mike Hommey461ad5c2012-04-20 08:38:42 +0200268static const ctl_indexed_node_t arenas_lrun_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800269 {INDEX(arenas_lrun_i)}
270};
271
Mike Hommey461ad5c2012-04-20 08:38:42 +0200272static const ctl_named_node_t arenas_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800273 {NAME("narenas"), CTL(arenas_narenas)},
274 {NAME("initialized"), CTL(arenas_initialized)},
275 {NAME("quantum"), CTL(arenas_quantum)},
Jason Evansae4c7b42012-04-02 07:04:34 -0700276 {NAME("page"), CTL(arenas_page)},
Jason Evansdafde142010-03-17 16:27:39 -0700277 {NAME("tcache_max"), CTL(arenas_tcache_max)},
Jason Evans3c234352010-01-27 13:10:55 -0800278 {NAME("nbins"), CTL(arenas_nbins)},
Jason Evansdafde142010-03-17 16:27:39 -0700279 {NAME("nhbins"), CTL(arenas_nhbins)},
Jason Evans65f343a2012-04-23 19:31:45 -0700280 {NAME("bin"), CHILD(indexed, arenas_bin)},
Jason Evans3c234352010-01-27 13:10:55 -0800281 {NAME("nlruns"), CTL(arenas_nlruns)},
Jason Evans65f343a2012-04-23 19:31:45 -0700282 {NAME("lrun"), CHILD(indexed, arenas_lrun)},
Jason Evans6005f072010-09-30 16:55:08 -0700283 {NAME("purge"), CTL(arenas_purge)}
Jason Evans3c234352010-01-27 13:10:55 -0800284};
285
Mike Hommey461ad5c2012-04-20 08:38:42 +0200286static const ctl_named_node_t prof_node[] = {
Jason Evansf18c9822010-03-31 18:43:24 -0700287 {NAME("active"), CTL(prof_active)},
Jason Evansd34f9e72010-02-11 13:19:21 -0800288 {NAME("dump"), CTL(prof_dump)},
289 {NAME("interval"), CTL(prof_interval)}
290};
Jason Evansd34f9e72010-02-11 13:19:21 -0800291
Mike Hommey461ad5c2012-04-20 08:38:42 +0200292static const ctl_named_node_t stats_chunks_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800293 {NAME("current"), CTL(stats_chunks_current)},
294 {NAME("total"), CTL(stats_chunks_total)},
295 {NAME("high"), CTL(stats_chunks_high)}
296};
297
Mike Hommey461ad5c2012-04-20 08:38:42 +0200298static const ctl_named_node_t stats_huge_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800299 {NAME("allocated"), CTL(stats_huge_allocated)},
300 {NAME("nmalloc"), CTL(stats_huge_nmalloc)},
301 {NAME("ndalloc"), CTL(stats_huge_ndalloc)}
302};
303
Mike Hommey461ad5c2012-04-20 08:38:42 +0200304static const ctl_named_node_t stats_arenas_i_small_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800305 {NAME("allocated"), CTL(stats_arenas_i_small_allocated)},
306 {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)},
Jason Evans86815df2010-03-13 20:32:56 -0800307 {NAME("ndalloc"), CTL(stats_arenas_i_small_ndalloc)},
308 {NAME("nrequests"), CTL(stats_arenas_i_small_nrequests)}
Jason Evans3c234352010-01-27 13:10:55 -0800309};
310
Mike Hommey461ad5c2012-04-20 08:38:42 +0200311static const ctl_named_node_t stats_arenas_i_large_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800312 {NAME("allocated"), CTL(stats_arenas_i_large_allocated)},
313 {NAME("nmalloc"), CTL(stats_arenas_i_large_nmalloc)},
Jason Evansdafde142010-03-17 16:27:39 -0700314 {NAME("ndalloc"), CTL(stats_arenas_i_large_ndalloc)},
315 {NAME("nrequests"), CTL(stats_arenas_i_large_nrequests)}
Jason Evans3c234352010-01-27 13:10:55 -0800316};
317
Mike Hommey461ad5c2012-04-20 08:38:42 +0200318static const ctl_named_node_t stats_arenas_i_bins_j_node[] = {
Jason Evans86815df2010-03-13 20:32:56 -0800319 {NAME("allocated"), CTL(stats_arenas_i_bins_j_allocated)},
320 {NAME("nmalloc"), CTL(stats_arenas_i_bins_j_nmalloc)},
321 {NAME("ndalloc"), CTL(stats_arenas_i_bins_j_ndalloc)},
Jason Evans3c234352010-01-27 13:10:55 -0800322 {NAME("nrequests"), CTL(stats_arenas_i_bins_j_nrequests)},
Jason Evans3c234352010-01-27 13:10:55 -0800323 {NAME("nfills"), CTL(stats_arenas_i_bins_j_nfills)},
324 {NAME("nflushes"), CTL(stats_arenas_i_bins_j_nflushes)},
Jason Evans3c234352010-01-27 13:10:55 -0800325 {NAME("nruns"), CTL(stats_arenas_i_bins_j_nruns)},
326 {NAME("nreruns"), CTL(stats_arenas_i_bins_j_nreruns)},
Jason Evans3c234352010-01-27 13:10:55 -0800327 {NAME("curruns"), CTL(stats_arenas_i_bins_j_curruns)}
328};
Mike Hommey461ad5c2012-04-20 08:38:42 +0200329static const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {
Jason Evans65f343a2012-04-23 19:31:45 -0700330 {NAME(""), CHILD(named, stats_arenas_i_bins_j)}
Jason Evans3c234352010-01-27 13:10:55 -0800331};
332
Mike Hommey461ad5c2012-04-20 08:38:42 +0200333static const ctl_indexed_node_t stats_arenas_i_bins_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800334 {INDEX(stats_arenas_i_bins_j)}
335};
336
Mike Hommey461ad5c2012-04-20 08:38:42 +0200337static const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {
Jason Evansdafde142010-03-17 16:27:39 -0700338 {NAME("nmalloc"), CTL(stats_arenas_i_lruns_j_nmalloc)},
339 {NAME("ndalloc"), CTL(stats_arenas_i_lruns_j_ndalloc)},
Jason Evans3c234352010-01-27 13:10:55 -0800340 {NAME("nrequests"), CTL(stats_arenas_i_lruns_j_nrequests)},
Jason Evans3c234352010-01-27 13:10:55 -0800341 {NAME("curruns"), CTL(stats_arenas_i_lruns_j_curruns)}
342};
Mike Hommey461ad5c2012-04-20 08:38:42 +0200343static const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {
Jason Evans65f343a2012-04-23 19:31:45 -0700344 {NAME(""), CHILD(named, stats_arenas_i_lruns_j)}
Jason Evans3c234352010-01-27 13:10:55 -0800345};
346
Mike Hommey461ad5c2012-04-20 08:38:42 +0200347static const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800348 {INDEX(stats_arenas_i_lruns_j)}
349};
Jason Evans3c234352010-01-27 13:10:55 -0800350
Mike Hommey461ad5c2012-04-20 08:38:42 +0200351static const ctl_named_node_t stats_arenas_i_node[] = {
Jason Evans597632b2011-03-18 13:41:33 -0700352 {NAME("nthreads"), CTL(stats_arenas_i_nthreads)},
Jason Evans3c234352010-01-27 13:10:55 -0800353 {NAME("pactive"), CTL(stats_arenas_i_pactive)},
Jason Evans7372b152012-02-10 20:22:09 -0800354 {NAME("pdirty"), CTL(stats_arenas_i_pdirty)},
Jason Evans3c234352010-01-27 13:10:55 -0800355 {NAME("mapped"), CTL(stats_arenas_i_mapped)},
356 {NAME("npurge"), CTL(stats_arenas_i_npurge)},
357 {NAME("nmadvise"), CTL(stats_arenas_i_nmadvise)},
358 {NAME("purged"), CTL(stats_arenas_i_purged)},
Jason Evans65f343a2012-04-23 19:31:45 -0700359 {NAME("small"), CHILD(named, stats_arenas_i_small)},
360 {NAME("large"), CHILD(named, stats_arenas_i_large)},
Jason Evans87667a82012-04-23 19:54:15 -0700361 {NAME("bins"), CHILD(indexed, stats_arenas_i_bins)},
362 {NAME("lruns"), CHILD(indexed, stats_arenas_i_lruns)}
Jason Evans3c234352010-01-27 13:10:55 -0800363};
Mike Hommey461ad5c2012-04-20 08:38:42 +0200364static const ctl_named_node_t super_stats_arenas_i_node[] = {
Jason Evans65f343a2012-04-23 19:31:45 -0700365 {NAME(""), CHILD(named, stats_arenas_i)}
Jason Evans3c234352010-01-27 13:10:55 -0800366};
367
Mike Hommey461ad5c2012-04-20 08:38:42 +0200368static const ctl_indexed_node_t stats_arenas_node[] = {
Jason Evans3c234352010-01-27 13:10:55 -0800369 {INDEX(stats_arenas_i)}
370};
371
Mike Hommey461ad5c2012-04-20 08:38:42 +0200372static const ctl_named_node_t stats_node[] = {
Jason Evans0657f122011-03-18 17:56:14 -0700373 {NAME("cactive"), CTL(stats_cactive)},
Jason Evans3c234352010-01-27 13:10:55 -0800374 {NAME("allocated"), CTL(stats_allocated)},
375 {NAME("active"), CTL(stats_active)},
376 {NAME("mapped"), CTL(stats_mapped)},
Jason Evans65f343a2012-04-23 19:31:45 -0700377 {NAME("chunks"), CHILD(named, stats_chunks)},
378 {NAME("huge"), CHILD(named, stats_huge)},
379 {NAME("arenas"), CHILD(indexed, stats_arenas)}
Jason Evans3c234352010-01-27 13:10:55 -0800380};
381
Mike Hommey461ad5c2012-04-20 08:38:42 +0200382static const ctl_named_node_t root_node[] = {
Jason Evansa40bc7a2010-03-02 13:01:16 -0800383 {NAME("version"), CTL(version)},
Jason Evans3c234352010-01-27 13:10:55 -0800384 {NAME("epoch"), CTL(epoch)},
Jason Evans65f343a2012-04-23 19:31:45 -0700385 {NAME("thread"), CHILD(named, thread)},
386 {NAME("config"), CHILD(named, config)},
387 {NAME("opt"), CHILD(named, opt)},
388 {NAME("arenas"), CHILD(named, arenas)},
389 {NAME("prof"), CHILD(named, prof)},
390 {NAME("stats"), CHILD(named, stats)}
Jason Evans3c234352010-01-27 13:10:55 -0800391};
Mike Hommey461ad5c2012-04-20 08:38:42 +0200392static const ctl_named_node_t super_root_node[] = {
Jason Evans65f343a2012-04-23 19:31:45 -0700393 {NAME(""), CHILD(named, root)}
Jason Evans3c234352010-01-27 13:10:55 -0800394};
395
396#undef NAME
397#undef CHILD
398#undef CTL
399#undef INDEX
400
401/******************************************************************************/
402
Jason Evans3c234352010-01-27 13:10:55 -0800403static bool
404ctl_arena_init(ctl_arena_stats_t *astats)
405{
406
Jason Evans3c234352010-01-27 13:10:55 -0800407 if (astats->lstats == NULL) {
408 astats->lstats = (malloc_large_stats_t *)base_alloc(nlclasses *
409 sizeof(malloc_large_stats_t));
410 if (astats->lstats == NULL)
411 return (true);
412 }
413
414 return (false);
415}
Jason Evans3c234352010-01-27 13:10:55 -0800416
417static void
418ctl_arena_clear(ctl_arena_stats_t *astats)
419{
420
421 astats->pactive = 0;
422 astats->pdirty = 0;
Jason Evans7372b152012-02-10 20:22:09 -0800423 if (config_stats) {
424 memset(&astats->astats, 0, sizeof(arena_stats_t));
425 astats->allocated_small = 0;
426 astats->nmalloc_small = 0;
427 astats->ndalloc_small = 0;
428 astats->nrequests_small = 0;
Jason Evansb1726102012-02-28 16:50:47 -0800429 memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));
Jason Evans7372b152012-02-10 20:22:09 -0800430 memset(astats->lstats, 0, nlclasses *
431 sizeof(malloc_large_stats_t));
432 }
Jason Evans3c234352010-01-27 13:10:55 -0800433}
434
Jason Evans86815df2010-03-13 20:32:56 -0800435static void
436ctl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena)
437{
438 unsigned i;
439
440 arena_stats_merge(arena, &cstats->pactive, &cstats->pdirty,
441 &cstats->astats, cstats->bstats, cstats->lstats);
442
Jason Evansb1726102012-02-28 16:50:47 -0800443 for (i = 0; i < NBINS; i++) {
Jason Evans86815df2010-03-13 20:32:56 -0800444 cstats->allocated_small += cstats->bstats[i].allocated;
445 cstats->nmalloc_small += cstats->bstats[i].nmalloc;
446 cstats->ndalloc_small += cstats->bstats[i].ndalloc;
447 cstats->nrequests_small += cstats->bstats[i].nrequests;
448 }
Jason Evans86815df2010-03-13 20:32:56 -0800449}
450
451static void
452ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)
453{
454 unsigned i;
455
456 sstats->pactive += astats->pactive;
457 sstats->pdirty += astats->pdirty;
458
459 sstats->astats.mapped += astats->astats.mapped;
460 sstats->astats.npurge += astats->astats.npurge;
461 sstats->astats.nmadvise += astats->astats.nmadvise;
462 sstats->astats.purged += astats->astats.purged;
463
464 sstats->allocated_small += astats->allocated_small;
465 sstats->nmalloc_small += astats->nmalloc_small;
466 sstats->ndalloc_small += astats->ndalloc_small;
467 sstats->nrequests_small += astats->nrequests_small;
468
Jason Evans86815df2010-03-13 20:32:56 -0800469 sstats->astats.allocated_large += astats->astats.allocated_large;
470 sstats->astats.nmalloc_large += astats->astats.nmalloc_large;
471 sstats->astats.ndalloc_large += astats->astats.ndalloc_large;
Jason Evansdafde142010-03-17 16:27:39 -0700472 sstats->astats.nrequests_large += astats->astats.nrequests_large;
Jason Evans86815df2010-03-13 20:32:56 -0800473
474 for (i = 0; i < nlclasses; i++) {
Jason Evansdafde142010-03-17 16:27:39 -0700475 sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;
476 sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;
Jason Evans86815df2010-03-13 20:32:56 -0800477 sstats->lstats[i].nrequests += astats->lstats[i].nrequests;
Jason Evans86815df2010-03-13 20:32:56 -0800478 sstats->lstats[i].curruns += astats->lstats[i].curruns;
479 }
480
Jason Evansb1726102012-02-28 16:50:47 -0800481 for (i = 0; i < NBINS; i++) {
Jason Evans86815df2010-03-13 20:32:56 -0800482 sstats->bstats[i].allocated += astats->bstats[i].allocated;
483 sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
484 sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
485 sstats->bstats[i].nrequests += astats->bstats[i].nrequests;
Jason Evans7372b152012-02-10 20:22:09 -0800486 if (config_tcache) {
487 sstats->bstats[i].nfills += astats->bstats[i].nfills;
488 sstats->bstats[i].nflushes +=
489 astats->bstats[i].nflushes;
490 }
Jason Evans86815df2010-03-13 20:32:56 -0800491 sstats->bstats[i].nruns += astats->bstats[i].nruns;
492 sstats->bstats[i].reruns += astats->bstats[i].reruns;
Jason Evans86815df2010-03-13 20:32:56 -0800493 sstats->bstats[i].curruns += astats->bstats[i].curruns;
494 }
495}
Jason Evans86815df2010-03-13 20:32:56 -0800496
Jason Evans3c234352010-01-27 13:10:55 -0800497static void
498ctl_arena_refresh(arena_t *arena, unsigned i)
499{
500 ctl_arena_stats_t *astats = &ctl_stats.arenas[i];
501 ctl_arena_stats_t *sstats = &ctl_stats.arenas[narenas];
502
503 ctl_arena_clear(astats);
504
Jason Evans597632b2011-03-18 13:41:33 -0700505 sstats->nthreads += astats->nthreads;
Jason Evans7372b152012-02-10 20:22:09 -0800506 if (config_stats) {
507 ctl_arena_stats_amerge(astats, arena);
508 /* Merge into sum stats as well. */
509 ctl_arena_stats_smerge(sstats, astats);
510 } else {
511 astats->pactive += arena->nactive;
512 astats->pdirty += arena->ndirty;
513 /* Merge into sum stats as well. */
514 sstats->pactive += arena->nactive;
515 sstats->pdirty += arena->ndirty;
516 }
Jason Evans3c234352010-01-27 13:10:55 -0800517}
518
519static void
520ctl_refresh(void)
521{
522 unsigned i;
Mike Hommey8b499712012-04-24 23:22:02 +0200523 VARIABLE_ARRAY(arena_t *, tarenas, narenas);
Jason Evans3c234352010-01-27 13:10:55 -0800524
Jason Evans7372b152012-02-10 20:22:09 -0800525 if (config_stats) {
526 malloc_mutex_lock(&chunks_mtx);
527 ctl_stats.chunks.current = stats_chunks.curchunks;
528 ctl_stats.chunks.total = stats_chunks.nchunks;
529 ctl_stats.chunks.high = stats_chunks.highchunks;
530 malloc_mutex_unlock(&chunks_mtx);
Jason Evans3c234352010-01-27 13:10:55 -0800531
Jason Evans7372b152012-02-10 20:22:09 -0800532 malloc_mutex_lock(&huge_mtx);
533 ctl_stats.huge.allocated = huge_allocated;
534 ctl_stats.huge.nmalloc = huge_nmalloc;
535 ctl_stats.huge.ndalloc = huge_ndalloc;
536 malloc_mutex_unlock(&huge_mtx);
537 }
Jason Evans3c234352010-01-27 13:10:55 -0800538
539 /*
Jason Evans13668262010-01-31 03:57:29 -0800540 * Clear sum stats, since they will be merged into by
Jason Evans3c234352010-01-27 13:10:55 -0800541 * ctl_arena_refresh().
542 */
Jason Evans597632b2011-03-18 13:41:33 -0700543 ctl_stats.arenas[narenas].nthreads = 0;
Jason Evans3c234352010-01-27 13:10:55 -0800544 ctl_arena_clear(&ctl_stats.arenas[narenas]);
545
546 malloc_mutex_lock(&arenas_lock);
547 memcpy(tarenas, arenas, sizeof(arena_t *) * narenas);
Jason Evans597632b2011-03-18 13:41:33 -0700548 for (i = 0; i < narenas; i++) {
549 if (arenas[i] != NULL)
550 ctl_stats.arenas[i].nthreads = arenas[i]->nthreads;
551 else
552 ctl_stats.arenas[i].nthreads = 0;
553 }
Jason Evans3c234352010-01-27 13:10:55 -0800554 malloc_mutex_unlock(&arenas_lock);
555 for (i = 0; i < narenas; i++) {
556 bool initialized = (tarenas[i] != NULL);
557
558 ctl_stats.arenas[i].initialized = initialized;
559 if (initialized)
560 ctl_arena_refresh(tarenas[i], i);
561 }
562
Jason Evans7372b152012-02-10 20:22:09 -0800563 if (config_stats) {
564 ctl_stats.allocated = ctl_stats.arenas[narenas].allocated_small
565 + ctl_stats.arenas[narenas].astats.allocated_large
566 + ctl_stats.huge.allocated;
567 ctl_stats.active = (ctl_stats.arenas[narenas].pactive <<
Jason Evansae4c7b42012-04-02 07:04:34 -0700568 LG_PAGE) + ctl_stats.huge.allocated;
Jason Evans7372b152012-02-10 20:22:09 -0800569 ctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk);
Jason Evans7372b152012-02-10 20:22:09 -0800570 }
Jason Evans3c234352010-01-27 13:10:55 -0800571
572 ctl_epoch++;
573}
574
575static bool
576ctl_init(void)
577{
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800578 bool ret;
Jason Evans3c234352010-01-27 13:10:55 -0800579
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800580 malloc_mutex_lock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -0800581 if (ctl_initialized == false) {
Jason Evans3c234352010-01-27 13:10:55 -0800582 /*
583 * Allocate space for one extra arena stats element, which
584 * contains summed stats across all arenas.
585 */
586 ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc(
587 (narenas + 1) * sizeof(ctl_arena_stats_t));
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800588 if (ctl_stats.arenas == NULL) {
589 ret = true;
Jason Evansa1ee7832012-04-10 15:07:44 -0700590 goto label_return;
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800591 }
Jason Evans3c234352010-01-27 13:10:55 -0800592 memset(ctl_stats.arenas, 0, (narenas + 1) *
593 sizeof(ctl_arena_stats_t));
594
595 /*
596 * Initialize all stats structures, regardless of whether they
597 * ever get used. Lazy initialization would allow errors to
598 * cause inconsistent state to be viewable by the application.
599 */
Jason Evans7372b152012-02-10 20:22:09 -0800600 if (config_stats) {
601 unsigned i;
602 for (i = 0; i <= narenas; i++) {
603 if (ctl_arena_init(&ctl_stats.arenas[i])) {
604 ret = true;
Jason Evansa1ee7832012-04-10 15:07:44 -0700605 goto label_return;
Jason Evans7372b152012-02-10 20:22:09 -0800606 }
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800607 }
Jason Evans3c234352010-01-27 13:10:55 -0800608 }
Jason Evans3c234352010-01-27 13:10:55 -0800609 ctl_stats.arenas[narenas].initialized = true;
610
611 ctl_epoch = 0;
612 ctl_refresh();
613 ctl_initialized = true;
614 }
615
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800616 ret = false;
Jason Evansa1ee7832012-04-10 15:07:44 -0700617label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800618 malloc_mutex_unlock(&ctl_mtx);
619 return (ret);
Jason Evans3c234352010-01-27 13:10:55 -0800620}
621
622static int
623ctl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp,
624 size_t *depthp)
625{
626 int ret;
627 const char *elm, *tdot, *dot;
628 size_t elen, i, j;
Mike Hommey461ad5c2012-04-20 08:38:42 +0200629 const ctl_named_node_t *node;
Jason Evans3c234352010-01-27 13:10:55 -0800630
631 elm = name;
632 /* Equivalent to strchrnul(). */
633 dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
634 elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
635 if (elen == 0) {
636 ret = ENOENT;
Jason Evansa1ee7832012-04-10 15:07:44 -0700637 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800638 }
639 node = super_root_node;
640 for (i = 0; i < *depthp; i++) {
Mike Hommey461ad5c2012-04-20 08:38:42 +0200641 assert(node);
642 assert(node->nchildren > 0);
643 if (ctl_named_node(node->children) != NULL) {
644 const ctl_named_node_t *pnode = node;
Jason Evans3c234352010-01-27 13:10:55 -0800645
646 /* Children are named. */
Mike Hommey461ad5c2012-04-20 08:38:42 +0200647 for (j = 0; j < node->nchildren; j++) {
648 const ctl_named_node_t *child =
649 ctl_named_children(node, j);
650 if (strlen(child->name) == elen &&
651 strncmp(elm, child->name, elen) == 0) {
Jason Evans3c234352010-01-27 13:10:55 -0800652 node = child;
653 if (nodesp != NULL)
Mike Hommey461ad5c2012-04-20 08:38:42 +0200654 nodesp[i] =
655 (const ctl_node_t *)node;
Jason Evans3c234352010-01-27 13:10:55 -0800656 mibp[i] = j;
657 break;
658 }
659 }
660 if (node == pnode) {
661 ret = ENOENT;
Jason Evansa1ee7832012-04-10 15:07:44 -0700662 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800663 }
664 } else {
Jason Evans41b6afb2012-02-02 22:04:57 -0800665 uintmax_t index;
Mike Hommey461ad5c2012-04-20 08:38:42 +0200666 const ctl_indexed_node_t *inode;
Jason Evans3c234352010-01-27 13:10:55 -0800667
668 /* Children are indexed. */
Jason Evans41b6afb2012-02-02 22:04:57 -0800669 index = malloc_strtoumax(elm, NULL, 10);
670 if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
Jason Evans3c234352010-01-27 13:10:55 -0800671 ret = ENOENT;
Jason Evansa1ee7832012-04-10 15:07:44 -0700672 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800673 }
674
Mike Hommey461ad5c2012-04-20 08:38:42 +0200675 inode = ctl_indexed_node(node->children);
676 node = inode->index(mibp, *depthp, (size_t)index);
Jason Evans3c234352010-01-27 13:10:55 -0800677 if (node == NULL) {
678 ret = ENOENT;
Jason Evansa1ee7832012-04-10 15:07:44 -0700679 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800680 }
681
682 if (nodesp != NULL)
Mike Hommey461ad5c2012-04-20 08:38:42 +0200683 nodesp[i] = (const ctl_node_t *)node;
Jason Evans3c234352010-01-27 13:10:55 -0800684 mibp[i] = (size_t)index;
685 }
686
687 if (node->ctl != NULL) {
688 /* Terminal node. */
689 if (*dot != '\0') {
690 /*
691 * The name contains more elements than are
692 * in this path through the tree.
693 */
694 ret = ENOENT;
Jason Evansa1ee7832012-04-10 15:07:44 -0700695 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800696 }
697 /* Complete lookup successful. */
698 *depthp = i + 1;
699 break;
700 }
701
702 /* Update elm. */
703 if (*dot == '\0') {
704 /* No more elements. */
705 ret = ENOENT;
Jason Evansa1ee7832012-04-10 15:07:44 -0700706 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800707 }
708 elm = &dot[1];
709 dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
710 strchr(elm, '\0');
711 elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
712 }
713
714 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -0700715label_return:
Jason Evans3c234352010-01-27 13:10:55 -0800716 return (ret);
717}
718
719int
720ctl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,
721 size_t newlen)
722{
723 int ret;
724 size_t depth;
725 ctl_node_t const *nodes[CTL_MAX_DEPTH];
726 size_t mib[CTL_MAX_DEPTH];
Mike Hommey461ad5c2012-04-20 08:38:42 +0200727 const ctl_named_node_t *node;
Jason Evans3c234352010-01-27 13:10:55 -0800728
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800729 if (ctl_initialized == false && ctl_init()) {
Jason Evans3c234352010-01-27 13:10:55 -0800730 ret = EAGAIN;
Jason Evansa1ee7832012-04-10 15:07:44 -0700731 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800732 }
733
734 depth = CTL_MAX_DEPTH;
735 ret = ctl_lookup(name, nodes, mib, &depth);
736 if (ret != 0)
Jason Evansa1ee7832012-04-10 15:07:44 -0700737 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800738
Mike Hommey461ad5c2012-04-20 08:38:42 +0200739 node = ctl_named_node(nodes[depth-1]);
740 if (node != NULL && node->ctl)
741 ret = node->ctl(mib, depth, oldp, oldlenp, newp, newlen);
742 else {
Jason Evans3c234352010-01-27 13:10:55 -0800743 /* The name refers to a partial path through the ctl tree. */
744 ret = ENOENT;
Jason Evans3c234352010-01-27 13:10:55 -0800745 }
Jason Evans3c234352010-01-27 13:10:55 -0800746
Jason Evansa1ee7832012-04-10 15:07:44 -0700747label_return:
Jason Evans3c234352010-01-27 13:10:55 -0800748 return(ret);
749}
750
751int
752ctl_nametomib(const char *name, size_t *mibp, size_t *miblenp)
753{
754 int ret;
755
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800756 if (ctl_initialized == false && ctl_init()) {
Jason Evans3c234352010-01-27 13:10:55 -0800757 ret = EAGAIN;
Jason Evansa1ee7832012-04-10 15:07:44 -0700758 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800759 }
760
761 ret = ctl_lookup(name, NULL, mibp, miblenp);
Jason Evansa1ee7832012-04-10 15:07:44 -0700762label_return:
Jason Evans3c234352010-01-27 13:10:55 -0800763 return(ret);
764}
765
766int
767ctl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
768 void *newp, size_t newlen)
769{
770 int ret;
Mike Hommey461ad5c2012-04-20 08:38:42 +0200771 const ctl_named_node_t *node;
Jason Evans3c234352010-01-27 13:10:55 -0800772 size_t i;
773
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800774 if (ctl_initialized == false && ctl_init()) {
Jason Evans3c234352010-01-27 13:10:55 -0800775 ret = EAGAIN;
Jason Evansa1ee7832012-04-10 15:07:44 -0700776 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800777 }
778
779 /* Iterate down the tree. */
780 node = super_root_node;
781 for (i = 0; i < miblen; i++) {
Mike Hommey461ad5c2012-04-20 08:38:42 +0200782 assert(node);
783 assert(node->nchildren > 0);
784 if (ctl_named_node(node->children) != NULL) {
Jason Evans3c234352010-01-27 13:10:55 -0800785 /* Children are named. */
Mike Hommey461ad5c2012-04-20 08:38:42 +0200786 if (node->nchildren <= mib[i]) {
Jason Evans3c234352010-01-27 13:10:55 -0800787 ret = ENOENT;
Jason Evansa1ee7832012-04-10 15:07:44 -0700788 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800789 }
Mike Hommey461ad5c2012-04-20 08:38:42 +0200790 node = ctl_named_children(node, mib[i]);
Jason Evans3c234352010-01-27 13:10:55 -0800791 } else {
Mike Hommey461ad5c2012-04-20 08:38:42 +0200792 const ctl_indexed_node_t *inode;
Jason Evans3c234352010-01-27 13:10:55 -0800793
794 /* Indexed element. */
Mike Hommey461ad5c2012-04-20 08:38:42 +0200795 inode = ctl_indexed_node(node->children);
796 node = inode->index(mib, miblen, mib[i]);
Jason Evans3c234352010-01-27 13:10:55 -0800797 if (node == NULL) {
798 ret = ENOENT;
Jason Evansa1ee7832012-04-10 15:07:44 -0700799 goto label_return;
Jason Evans3c234352010-01-27 13:10:55 -0800800 }
801 }
802 }
803
804 /* Call the ctl function. */
Mike Hommey461ad5c2012-04-20 08:38:42 +0200805 if (node && node->ctl)
806 ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen);
807 else {
Jason Evans3c234352010-01-27 13:10:55 -0800808 /* Partial MIB. */
809 ret = ENOENT;
Jason Evans3c234352010-01-27 13:10:55 -0800810 }
Jason Evans3c234352010-01-27 13:10:55 -0800811
Jason Evansa1ee7832012-04-10 15:07:44 -0700812label_return:
Jason Evans3c234352010-01-27 13:10:55 -0800813 return(ret);
814}
815
816bool
817ctl_boot(void)
818{
819
820 if (malloc_mutex_init(&ctl_mtx))
821 return (true);
822
823 ctl_initialized = false;
824
825 return (false);
826}
827
828/******************************************************************************/
829/* *_ctl() functions. */
830
831#define READONLY() do { \
832 if (newp != NULL || newlen != 0) { \
833 ret = EPERM; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700834 goto label_return; \
Jason Evans3c234352010-01-27 13:10:55 -0800835 } \
836} while (0)
837
Jason Evans22ca8552010-03-02 11:57:30 -0800838#define WRITEONLY() do { \
Jason Evans3c234352010-01-27 13:10:55 -0800839 if (oldp != NULL || oldlenp != NULL) { \
840 ret = EPERM; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700841 goto label_return; \
Jason Evans3c234352010-01-27 13:10:55 -0800842 } \
843} while (0)
844
845#define READ(v, t) do { \
846 if (oldp != NULL && oldlenp != NULL) { \
847 if (*oldlenp != sizeof(t)) { \
848 size_t copylen = (sizeof(t) <= *oldlenp) \
849 ? sizeof(t) : *oldlenp; \
850 memcpy(oldp, (void *)&v, copylen); \
851 ret = EINVAL; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700852 goto label_return; \
Jason Evans3c234352010-01-27 13:10:55 -0800853 } else \
854 *(t *)oldp = v; \
855 } \
856} while (0)
857
858#define WRITE(v, t) do { \
859 if (newp != NULL) { \
860 if (newlen != sizeof(t)) { \
861 ret = EINVAL; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700862 goto label_return; \
Jason Evans3c234352010-01-27 13:10:55 -0800863 } \
864 v = *(t *)newp; \
865 } \
866} while (0)
867
Jason Evans7372b152012-02-10 20:22:09 -0800868/*
869 * There's a lot of code duplication in the following macros due to limitations
870 * in how nested cpp macros are expanded.
871 */
872#define CTL_RO_CLGEN(c, l, n, v, t) \
873static int \
874n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
875 void *newp, size_t newlen) \
876{ \
877 int ret; \
878 t oldval; \
879 \
880 if ((c) == false) \
881 return (ENOENT); \
882 if (l) \
883 malloc_mutex_lock(&ctl_mtx); \
884 READONLY(); \
885 oldval = v; \
886 READ(oldval, t); \
887 \
888 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700889label_return: \
Jason Evans7372b152012-02-10 20:22:09 -0800890 if (l) \
891 malloc_mutex_unlock(&ctl_mtx); \
892 return (ret); \
893}
894
895#define CTL_RO_CGEN(c, n, v, t) \
896static int \
897n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
898 void *newp, size_t newlen) \
899{ \
900 int ret; \
901 t oldval; \
902 \
903 if ((c) == false) \
904 return (ENOENT); \
905 malloc_mutex_lock(&ctl_mtx); \
906 READONLY(); \
907 oldval = v; \
908 READ(oldval, t); \
909 \
910 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700911label_return: \
Jason Evans7372b152012-02-10 20:22:09 -0800912 malloc_mutex_unlock(&ctl_mtx); \
913 return (ret); \
914}
915
Jason Evans3c234352010-01-27 13:10:55 -0800916#define CTL_RO_GEN(n, v, t) \
917static int \
918n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
919 void *newp, size_t newlen) \
920{ \
921 int ret; \
922 t oldval; \
923 \
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800924 malloc_mutex_lock(&ctl_mtx); \
925 READONLY(); \
926 oldval = v; \
927 READ(oldval, t); \
928 \
929 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700930label_return: \
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800931 malloc_mutex_unlock(&ctl_mtx); \
932 return (ret); \
933}
934
935/*
936 * ctl_mtx is not acquired, under the assumption that no pertinent data will
937 * mutate during the call.
938 */
Jason Evans7372b152012-02-10 20:22:09 -0800939#define CTL_RO_NL_CGEN(c, n, v, t) \
940static int \
941n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
942 void *newp, size_t newlen) \
943{ \
944 int ret; \
945 t oldval; \
946 \
947 if ((c) == false) \
948 return (ENOENT); \
949 READONLY(); \
950 oldval = v; \
951 READ(oldval, t); \
952 \
953 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700954label_return: \
Jason Evans7372b152012-02-10 20:22:09 -0800955 return (ret); \
956}
957
958#define CTL_RO_NL_GEN(n, v, t) \
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800959static int \
960n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
961 void *newp, size_t newlen) \
962{ \
963 int ret; \
964 t oldval; \
965 \
Jason Evans3c234352010-01-27 13:10:55 -0800966 READONLY(); \
967 oldval = v; \
968 READ(oldval, t); \
969 \
970 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700971label_return: \
Jason Evans3c234352010-01-27 13:10:55 -0800972 return (ret); \
973}
974
Jason Evans7372b152012-02-10 20:22:09 -0800975#define CTL_RO_BOOL_CONFIG_GEN(n) \
Jason Evans3c234352010-01-27 13:10:55 -0800976static int \
977n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
978 void *newp, size_t newlen) \
979{ \
980 int ret; \
981 bool oldval; \
982 \
983 READONLY(); \
Jason Evans7372b152012-02-10 20:22:09 -0800984 oldval = n; \
Jason Evans3c234352010-01-27 13:10:55 -0800985 READ(oldval, bool); \
986 \
987 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700988label_return: \
Jason Evans3c234352010-01-27 13:10:55 -0800989 return (ret); \
990}
991
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800992CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
Jason Evansa40bc7a2010-03-02 13:01:16 -0800993
Jason Evans3c234352010-01-27 13:10:55 -0800994static int
995epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
996 void *newp, size_t newlen)
997{
998 int ret;
999 uint64_t newval;
1000
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001001 malloc_mutex_lock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -08001002 WRITE(newval, uint64_t);
Jason Evans6b9ed672012-04-25 13:12:46 -07001003 if (newp != NULL)
Jason Evans3c234352010-01-27 13:10:55 -08001004 ctl_refresh();
1005 READ(ctl_epoch, uint64_t);
1006
1007 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001008label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001009 malloc_mutex_unlock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -08001010 return (ret);
1011}
1012
Jason Evans3c234352010-01-27 13:10:55 -08001013static int
Jason Evansd4be8b72012-03-26 18:54:44 -07001014thread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp,
1015 size_t *oldlenp, void *newp, size_t newlen)
1016{
1017 int ret;
1018 bool oldval;
1019
1020 if (config_tcache == false)
1021 return (ENOENT);
1022
1023 oldval = tcache_enabled_get();
1024 if (newp != NULL) {
1025 if (newlen != sizeof(bool)) {
1026 ret = EINVAL;
Jason Evansa1ee7832012-04-10 15:07:44 -07001027 goto label_return;
Jason Evansd4be8b72012-03-26 18:54:44 -07001028 }
1029 tcache_enabled_set(*(bool *)newp);
1030 }
1031 READ(oldval, bool);
1032
Jason Evansa1ee7832012-04-10 15:07:44 -07001033label_return:
Jason Evansd4be8b72012-03-26 18:54:44 -07001034 ret = 0;
1035 return (ret);
1036}
1037
1038static int
Jason Evanse7b8fa12012-03-16 17:09:32 -07001039thread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp,
1040 size_t *oldlenp, void *newp, size_t newlen)
Jason Evans3c234352010-01-27 13:10:55 -08001041{
1042 int ret;
Jason Evans3c234352010-01-27 13:10:55 -08001043
Jason Evans7372b152012-02-10 20:22:09 -08001044 if (config_tcache == false)
1045 return (ENOENT);
1046
Mike Hommeyaf04b742012-04-30 12:38:25 +02001047 READONLY();
1048 WRITEONLY();
Jason Evans3c234352010-01-27 13:10:55 -08001049
Jason Evansd4be8b72012-03-26 18:54:44 -07001050 tcache_flush();
Jason Evans3c234352010-01-27 13:10:55 -08001051
1052 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001053label_return:
Jason Evans3c234352010-01-27 13:10:55 -08001054 return (ret);
1055}
Jason Evans3c234352010-01-27 13:10:55 -08001056
Jason Evansb267d0f2010-08-13 15:42:29 -07001057static int
1058thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1059 void *newp, size_t newlen)
1060{
1061 int ret;
1062 unsigned newind, oldind;
1063
Jason Evans01b3fe52012-04-03 09:28:00 -07001064 newind = oldind = choose_arena(NULL)->ind;
Jason Evansa7153a02011-03-14 11:39:49 -07001065 WRITE(newind, unsigned);
1066 READ(oldind, unsigned);
Jason Evansb267d0f2010-08-13 15:42:29 -07001067 if (newind != oldind) {
1068 arena_t *arena;
1069
1070 if (newind >= narenas) {
1071 /* New arena index is out of range. */
1072 ret = EFAULT;
Jason Evansa1ee7832012-04-10 15:07:44 -07001073 goto label_return;
Jason Evansb267d0f2010-08-13 15:42:29 -07001074 }
1075
1076 /* Initialize arena if necessary. */
1077 malloc_mutex_lock(&arenas_lock);
Jason Evanscd9a1342012-03-21 18:33:03 -07001078 if ((arena = arenas[newind]) == NULL && (arena =
1079 arenas_extend(newind)) == NULL) {
1080 malloc_mutex_unlock(&arenas_lock);
Jason Evansb267d0f2010-08-13 15:42:29 -07001081 ret = EAGAIN;
Jason Evansa1ee7832012-04-10 15:07:44 -07001082 goto label_return;
Jason Evansb267d0f2010-08-13 15:42:29 -07001083 }
Jason Evanscd9a1342012-03-21 18:33:03 -07001084 assert(arena == arenas[newind]);
1085 arenas[oldind]->nthreads--;
1086 arenas[newind]->nthreads++;
1087 malloc_mutex_unlock(&arenas_lock);
Jason Evansb267d0f2010-08-13 15:42:29 -07001088
1089 /* Set new arena association. */
Jason Evans7372b152012-02-10 20:22:09 -08001090 if (config_tcache) {
Jason Evanscd9a1342012-03-21 18:33:03 -07001091 tcache_t *tcache;
Jason Evans122449b2012-04-06 00:35:09 -07001092 if ((uintptr_t)(tcache = *tcache_tsd_get()) >
1093 (uintptr_t)TCACHE_STATE_MAX) {
Jason Evanscd9a1342012-03-21 18:33:03 -07001094 tcache_arena_dissociate(tcache);
1095 tcache_arena_associate(tcache, arena);
1096 }
Jason Evans624f2f32010-12-29 12:21:05 -08001097 }
Jason Evanscd9a1342012-03-21 18:33:03 -07001098 arenas_tsd_set(&arena);
Jason Evansb267d0f2010-08-13 15:42:29 -07001099 }
1100
1101 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001102label_return:
Jason Evansb267d0f2010-08-13 15:42:29 -07001103 return (ret);
1104}
Jason Evansb267d0f2010-08-13 15:42:29 -07001105
Jason Evanscd9a1342012-03-21 18:33:03 -07001106CTL_RO_NL_CGEN(config_stats, thread_allocated,
1107 thread_allocated_tsd_get()->allocated, uint64_t)
1108CTL_RO_NL_CGEN(config_stats, thread_allocatedp,
1109 &thread_allocated_tsd_get()->allocated, uint64_t *)
1110CTL_RO_NL_CGEN(config_stats, thread_deallocated,
1111 thread_allocated_tsd_get()->deallocated, uint64_t)
1112CTL_RO_NL_CGEN(config_stats, thread_deallocatedp,
1113 &thread_allocated_tsd_get()->deallocated, uint64_t *)
Jason Evans93443682010-10-20 17:39:18 -07001114
Jason Evans3c234352010-01-27 13:10:55 -08001115/******************************************************************************/
1116
Jason Evans7372b152012-02-10 20:22:09 -08001117CTL_RO_BOOL_CONFIG_GEN(config_debug)
1118CTL_RO_BOOL_CONFIG_GEN(config_dss)
Jason Evans7372b152012-02-10 20:22:09 -08001119CTL_RO_BOOL_CONFIG_GEN(config_fill)
1120CTL_RO_BOOL_CONFIG_GEN(config_lazy_lock)
Jason Evans59ae2762012-04-16 17:52:27 -07001121CTL_RO_BOOL_CONFIG_GEN(config_munmap)
Jason Evans7372b152012-02-10 20:22:09 -08001122CTL_RO_BOOL_CONFIG_GEN(config_prof)
1123CTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc)
1124CTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind)
1125CTL_RO_BOOL_CONFIG_GEN(config_stats)
Jason Evans7372b152012-02-10 20:22:09 -08001126CTL_RO_BOOL_CONFIG_GEN(config_tcache)
Jason Evans7372b152012-02-10 20:22:09 -08001127CTL_RO_BOOL_CONFIG_GEN(config_tls)
Jason Evansb1476112012-04-05 13:36:17 -07001128CTL_RO_BOOL_CONFIG_GEN(config_utrace)
Jason Evans122449b2012-04-06 00:35:09 -07001129CTL_RO_BOOL_CONFIG_GEN(config_valgrind)
Jason Evans7372b152012-02-10 20:22:09 -08001130CTL_RO_BOOL_CONFIG_GEN(config_xmalloc)
Jason Evans3c234352010-01-27 13:10:55 -08001131
1132/******************************************************************************/
1133
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001134CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001135CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
1136CTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t)
1137CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
1138CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
Jason Evans7372b152012-02-10 20:22:09 -08001139CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool)
1140CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
Jason Evans122449b2012-04-06 00:35:09 -07001141CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
1142CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
Jason Evansb1476112012-04-05 13:36:17 -07001143CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
Jason Evans122449b2012-04-06 00:35:09 -07001144CTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool)
Jason Evans7372b152012-02-10 20:22:09 -08001145CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
1146CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
Jason Evansf3ca7c82012-04-04 16:16:09 -07001147CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
Jason Evans7372b152012-02-10 20:22:09 -08001148CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
1149CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
1150CTL_RO_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) /* Mutable. */
Jason Evans7372b152012-02-10 20:22:09 -08001151CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
1152CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
1153CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
Jason Evans0b25fe72012-04-17 16:39:33 -07001154CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
Jason Evans7372b152012-02-10 20:22:09 -08001155CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
1156CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
Jason Evans3c234352010-01-27 13:10:55 -08001157
1158/******************************************************************************/
1159
Jason Evans49f7e8f2011-03-15 13:59:15 -07001160CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)
1161CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)
1162CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)
Mike Hommey461ad5c2012-04-20 08:38:42 +02001163const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001164arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)
1165{
1166
Jason Evansb1726102012-02-28 16:50:47 -08001167 if (i > NBINS)
Jason Evans3c234352010-01-27 13:10:55 -08001168 return (NULL);
1169 return (super_arenas_bin_i_node);
1170}
1171
Jason Evansae4c7b42012-04-02 07:04:34 -07001172CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t)
Mike Hommey461ad5c2012-04-20 08:38:42 +02001173const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001174arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)
1175{
1176
1177 if (i > nlclasses)
1178 return (NULL);
1179 return (super_arenas_lrun_i_node);
1180}
1181
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001182CTL_RO_NL_GEN(arenas_narenas, narenas, unsigned)
Jason Evans3c234352010-01-27 13:10:55 -08001183
1184static int
1185arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,
1186 size_t *oldlenp, void *newp, size_t newlen)
1187{
1188 int ret;
1189 unsigned nread, i;
1190
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001191 malloc_mutex_lock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -08001192 READONLY();
1193 if (*oldlenp != narenas * sizeof(bool)) {
1194 ret = EINVAL;
1195 nread = (*oldlenp < narenas * sizeof(bool))
1196 ? (*oldlenp / sizeof(bool)) : narenas;
1197 } else {
1198 ret = 0;
1199 nread = narenas;
1200 }
1201
1202 for (i = 0; i < nread; i++)
1203 ((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
1204
Jason Evansa1ee7832012-04-10 15:07:44 -07001205label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001206 malloc_mutex_unlock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -08001207 return (ret);
1208}
1209
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001210CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
Jason Evansae4c7b42012-04-02 07:04:34 -07001211CTL_RO_NL_GEN(arenas_page, PAGE, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001212CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)
Jason Evansb1726102012-02-28 16:50:47 -08001213CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)
Jason Evans7372b152012-02-10 20:22:09 -08001214CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001215CTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t)
Jason Evans3c234352010-01-27 13:10:55 -08001216
Jason Evans6005f072010-09-30 16:55:08 -07001217static int
1218arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1219 void *newp, size_t newlen)
1220{
1221 int ret;
1222 unsigned arena;
1223
1224 WRITEONLY();
1225 arena = UINT_MAX;
1226 WRITE(arena, unsigned);
1227 if (newp != NULL && arena >= narenas) {
1228 ret = EFAULT;
Jason Evansa1ee7832012-04-10 15:07:44 -07001229 goto label_return;
Jason Evans6005f072010-09-30 16:55:08 -07001230 } else {
Mike Hommey8b499712012-04-24 23:22:02 +02001231 VARIABLE_ARRAY(arena_t *, tarenas, narenas);
Jason Evans6005f072010-09-30 16:55:08 -07001232
1233 malloc_mutex_lock(&arenas_lock);
1234 memcpy(tarenas, arenas, sizeof(arena_t *) * narenas);
1235 malloc_mutex_unlock(&arenas_lock);
1236
1237 if (arena == UINT_MAX) {
Jason Evans1506a1b2010-10-07 08:52:32 -07001238 unsigned i;
1239 for (i = 0; i < narenas; i++) {
Jason Evans6005f072010-09-30 16:55:08 -07001240 if (tarenas[i] != NULL)
1241 arena_purge_all(tarenas[i]);
1242 }
1243 } else {
1244 assert(arena < narenas);
1245 if (tarenas[arena] != NULL)
1246 arena_purge_all(tarenas[arena]);
1247 }
1248 }
1249
1250 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001251label_return:
Jason Evans6005f072010-09-30 16:55:08 -07001252 return (ret);
1253}
1254
Jason Evans3c234352010-01-27 13:10:55 -08001255/******************************************************************************/
1256
Jason Evansd34f9e72010-02-11 13:19:21 -08001257static int
Jason Evansf18c9822010-03-31 18:43:24 -07001258prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1259 void *newp, size_t newlen)
1260{
1261 int ret;
1262 bool oldval;
1263
Jason Evans7372b152012-02-10 20:22:09 -08001264 if (config_prof == false)
1265 return (ENOENT);
1266
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001267 malloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */
Jason Evansf18c9822010-03-31 18:43:24 -07001268 oldval = opt_prof_active;
1269 if (newp != NULL) {
1270 /*
1271 * The memory barriers will tend to make opt_prof_active
1272 * propagate faster on systems with weak memory ordering.
1273 */
1274 mb_write();
1275 WRITE(opt_prof_active, bool);
1276 mb_write();
1277 }
1278 READ(oldval, bool);
1279
1280 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001281label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001282 malloc_mutex_unlock(&ctl_mtx);
Jason Evansf18c9822010-03-31 18:43:24 -07001283 return (ret);
1284}
1285
1286static int
Jason Evansd34f9e72010-02-11 13:19:21 -08001287prof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1288 void *newp, size_t newlen)
1289{
1290 int ret;
Jason Evans22ca8552010-03-02 11:57:30 -08001291 const char *filename = NULL;
Jason Evansd34f9e72010-02-11 13:19:21 -08001292
Jason Evans7372b152012-02-10 20:22:09 -08001293 if (config_prof == false)
1294 return (ENOENT);
1295
Jason Evans22ca8552010-03-02 11:57:30 -08001296 WRITEONLY();
1297 WRITE(filename, const char *);
Jason Evansd34f9e72010-02-11 13:19:21 -08001298
Jason Evans22ca8552010-03-02 11:57:30 -08001299 if (prof_mdump(filename)) {
1300 ret = EFAULT;
Jason Evansa1ee7832012-04-10 15:07:44 -07001301 goto label_return;
Jason Evans22ca8552010-03-02 11:57:30 -08001302 }
Jason Evansd34f9e72010-02-11 13:19:21 -08001303
1304 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001305label_return:
Jason Evansd34f9e72010-02-11 13:19:21 -08001306 return (ret);
1307}
1308
Jason Evans7372b152012-02-10 20:22:09 -08001309CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
Jason Evansd34f9e72010-02-11 13:19:21 -08001310
1311/******************************************************************************/
1312
Jason Evans7372b152012-02-10 20:22:09 -08001313CTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current,
1314 size_t)
1315CTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t)
1316CTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t)
1317CTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t)
1318CTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t)
1319CTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t)
1320CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
Jason Evans86815df2010-03-13 20:32:56 -08001321 ctl_stats.arenas[mib[2]].allocated_small, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001322CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
Jason Evans86815df2010-03-13 20:32:56 -08001323 ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001324CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
Jason Evans86815df2010-03-13 20:32:56 -08001325 ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001326CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
Jason Evans86815df2010-03-13 20:32:56 -08001327 ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001328CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
Jason Evans3c234352010-01-27 13:10:55 -08001329 ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001330CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
Jason Evans3c234352010-01-27 13:10:55 -08001331 ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001332CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
Jason Evans3c234352010-01-27 13:10:55 -08001333 ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001334CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
Jason Evansdafde142010-03-17 16:27:39 -07001335 ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)
Jason Evans3c234352010-01-27 13:10:55 -08001336
Jason Evans7372b152012-02-10 20:22:09 -08001337CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated,
Jason Evans86815df2010-03-13 20:32:56 -08001338 ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001339CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
Jason Evans86815df2010-03-13 20:32:56 -08001340 ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001341CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
Jason Evans86815df2010-03-13 20:32:56 -08001342 ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001343CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
Jason Evans3c234352010-01-27 13:10:55 -08001344 ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001345CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,
Jason Evans3c234352010-01-27 13:10:55 -08001346 ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001347CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,
Jason Evans3c234352010-01-27 13:10:55 -08001348 ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001349CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,
Jason Evans3c234352010-01-27 13:10:55 -08001350 ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001351CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,
Jason Evans3c234352010-01-27 13:10:55 -08001352 ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001353CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,
Jason Evans3c234352010-01-27 13:10:55 -08001354 ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)
1355
Mike Hommey461ad5c2012-04-20 08:38:42 +02001356const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001357stats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j)
1358{
1359
Jason Evansb1726102012-02-28 16:50:47 -08001360 if (j > NBINS)
Jason Evans3c234352010-01-27 13:10:55 -08001361 return (NULL);
1362 return (super_stats_arenas_i_bins_j_node);
1363}
1364
Jason Evans7372b152012-02-10 20:22:09 -08001365CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,
Jason Evansdafde142010-03-17 16:27:39 -07001366 ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001367CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,
Jason Evansdafde142010-03-17 16:27:39 -07001368 ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001369CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,
Jason Evans3c234352010-01-27 13:10:55 -08001370 ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001371CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,
Jason Evans3c234352010-01-27 13:10:55 -08001372 ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)
Jason Evans3c234352010-01-27 13:10:55 -08001373
Mike Hommey461ad5c2012-04-20 08:38:42 +02001374const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001375stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j)
1376{
1377
1378 if (j > nlclasses)
1379 return (NULL);
1380 return (super_stats_arenas_i_lruns_j_node);
1381}
1382
Jason Evans597632b2011-03-18 13:41:33 -07001383CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)
Jason Evans3c234352010-01-27 13:10:55 -08001384CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
1385CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001386CTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
1387 ctl_stats.arenas[mib[2]].astats.mapped, size_t)
1388CTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
1389 ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
1390CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
1391 ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)
1392CTL_RO_CGEN(config_stats, stats_arenas_i_purged,
1393 ctl_stats.arenas[mib[2]].astats.purged, uint64_t)
Jason Evans3c234352010-01-27 13:10:55 -08001394
Mike Hommey461ad5c2012-04-20 08:38:42 +02001395const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001396stats_arenas_i_index(const size_t *mib, size_t miblen, size_t i)
1397{
Mike Hommey461ad5c2012-04-20 08:38:42 +02001398 const ctl_named_node_t * ret;
Jason Evans3c234352010-01-27 13:10:55 -08001399
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001400 malloc_mutex_lock(&ctl_mtx);
1401 if (ctl_stats.arenas[i].initialized == false) {
1402 ret = NULL;
Jason Evansa1ee7832012-04-10 15:07:44 -07001403 goto label_return;
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001404 }
1405
1406 ret = super_stats_arenas_i_node;
Jason Evansa1ee7832012-04-10 15:07:44 -07001407label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001408 malloc_mutex_unlock(&ctl_mtx);
1409 return (ret);
Jason Evans3c234352010-01-27 13:10:55 -08001410}
1411
Jason Evans7372b152012-02-10 20:22:09 -08001412CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)
1413CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)
1414CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
1415CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)