blob: 4b41d1d3b357c2b22498ba80ab7f21fd7817ada4 [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;
523 arena_t *tarenas[narenas];
524
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
Jason Evans22ca8552010-03-02 11:57:30 -0800845#define VOID() do { \
846 READONLY(); \
847 WRITEONLY(); \
848} while (0)
849
Jason Evans3c234352010-01-27 13:10:55 -0800850#define READ(v, t) do { \
851 if (oldp != NULL && oldlenp != NULL) { \
852 if (*oldlenp != sizeof(t)) { \
853 size_t copylen = (sizeof(t) <= *oldlenp) \
854 ? sizeof(t) : *oldlenp; \
855 memcpy(oldp, (void *)&v, copylen); \
856 ret = EINVAL; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700857 goto label_return; \
Jason Evans3c234352010-01-27 13:10:55 -0800858 } else \
859 *(t *)oldp = v; \
860 } \
861} while (0)
862
863#define WRITE(v, t) do { \
864 if (newp != NULL) { \
865 if (newlen != sizeof(t)) { \
866 ret = EINVAL; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700867 goto label_return; \
Jason Evans3c234352010-01-27 13:10:55 -0800868 } \
869 v = *(t *)newp; \
870 } \
871} while (0)
872
Jason Evans7372b152012-02-10 20:22:09 -0800873/*
874 * There's a lot of code duplication in the following macros due to limitations
875 * in how nested cpp macros are expanded.
876 */
877#define CTL_RO_CLGEN(c, l, n, v, t) \
878static int \
879n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
880 void *newp, size_t newlen) \
881{ \
882 int ret; \
883 t oldval; \
884 \
885 if ((c) == false) \
886 return (ENOENT); \
887 if (l) \
888 malloc_mutex_lock(&ctl_mtx); \
889 READONLY(); \
890 oldval = v; \
891 READ(oldval, t); \
892 \
893 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700894label_return: \
Jason Evans7372b152012-02-10 20:22:09 -0800895 if (l) \
896 malloc_mutex_unlock(&ctl_mtx); \
897 return (ret); \
898}
899
900#define CTL_RO_CGEN(c, n, v, t) \
901static int \
902n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
903 void *newp, size_t newlen) \
904{ \
905 int ret; \
906 t oldval; \
907 \
908 if ((c) == false) \
909 return (ENOENT); \
910 malloc_mutex_lock(&ctl_mtx); \
911 READONLY(); \
912 oldval = v; \
913 READ(oldval, t); \
914 \
915 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700916label_return: \
Jason Evans7372b152012-02-10 20:22:09 -0800917 malloc_mutex_unlock(&ctl_mtx); \
918 return (ret); \
919}
920
Jason Evans3c234352010-01-27 13:10:55 -0800921#define CTL_RO_GEN(n, v, t) \
922static int \
923n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
924 void *newp, size_t newlen) \
925{ \
926 int ret; \
927 t oldval; \
928 \
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800929 malloc_mutex_lock(&ctl_mtx); \
930 READONLY(); \
931 oldval = v; \
932 READ(oldval, t); \
933 \
934 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700935label_return: \
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800936 malloc_mutex_unlock(&ctl_mtx); \
937 return (ret); \
938}
939
940/*
941 * ctl_mtx is not acquired, under the assumption that no pertinent data will
942 * mutate during the call.
943 */
Jason Evans7372b152012-02-10 20:22:09 -0800944#define CTL_RO_NL_CGEN(c, n, v, t) \
945static int \
946n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
947 void *newp, size_t newlen) \
948{ \
949 int ret; \
950 t oldval; \
951 \
952 if ((c) == false) \
953 return (ENOENT); \
954 READONLY(); \
955 oldval = v; \
956 READ(oldval, t); \
957 \
958 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700959label_return: \
Jason Evans7372b152012-02-10 20:22:09 -0800960 return (ret); \
961}
962
963#define CTL_RO_NL_GEN(n, v, t) \
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800964static int \
965n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
966 void *newp, size_t newlen) \
967{ \
968 int ret; \
969 t oldval; \
970 \
Jason Evans3c234352010-01-27 13:10:55 -0800971 READONLY(); \
972 oldval = v; \
973 READ(oldval, t); \
974 \
975 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700976label_return: \
Jason Evans3c234352010-01-27 13:10:55 -0800977 return (ret); \
978}
979
Jason Evans7372b152012-02-10 20:22:09 -0800980#define CTL_RO_BOOL_CONFIG_GEN(n) \
Jason Evans3c234352010-01-27 13:10:55 -0800981static int \
982n##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp, \
983 void *newp, size_t newlen) \
984{ \
985 int ret; \
986 bool oldval; \
987 \
988 READONLY(); \
Jason Evans7372b152012-02-10 20:22:09 -0800989 oldval = n; \
Jason Evans3c234352010-01-27 13:10:55 -0800990 READ(oldval, bool); \
991 \
992 ret = 0; \
Jason Evans6b9ed672012-04-25 13:12:46 -0700993label_return: \
Jason Evans3c234352010-01-27 13:10:55 -0800994 return (ret); \
995}
996
Jason Evansfc4dcfa2010-11-24 15:44:21 -0800997CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
Jason Evansa40bc7a2010-03-02 13:01:16 -0800998
Jason Evans3c234352010-01-27 13:10:55 -0800999static int
1000epoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1001 void *newp, size_t newlen)
1002{
1003 int ret;
1004 uint64_t newval;
1005
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001006 malloc_mutex_lock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -08001007 WRITE(newval, uint64_t);
Jason Evans6b9ed672012-04-25 13:12:46 -07001008 if (newp != NULL)
Jason Evans3c234352010-01-27 13:10:55 -08001009 ctl_refresh();
1010 READ(ctl_epoch, uint64_t);
1011
1012 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001013label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001014 malloc_mutex_unlock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -08001015 return (ret);
1016}
1017
Jason Evans3c234352010-01-27 13:10:55 -08001018static int
Jason Evansd4be8b72012-03-26 18:54:44 -07001019thread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp,
1020 size_t *oldlenp, void *newp, size_t newlen)
1021{
1022 int ret;
1023 bool oldval;
1024
1025 if (config_tcache == false)
1026 return (ENOENT);
1027
1028 oldval = tcache_enabled_get();
1029 if (newp != NULL) {
1030 if (newlen != sizeof(bool)) {
1031 ret = EINVAL;
Jason Evansa1ee7832012-04-10 15:07:44 -07001032 goto label_return;
Jason Evansd4be8b72012-03-26 18:54:44 -07001033 }
1034 tcache_enabled_set(*(bool *)newp);
1035 }
1036 READ(oldval, bool);
1037
Jason Evansa1ee7832012-04-10 15:07:44 -07001038label_return:
Jason Evansd4be8b72012-03-26 18:54:44 -07001039 ret = 0;
1040 return (ret);
1041}
1042
1043static int
Jason Evanse7b8fa12012-03-16 17:09:32 -07001044thread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp,
1045 size_t *oldlenp, void *newp, size_t newlen)
Jason Evans3c234352010-01-27 13:10:55 -08001046{
1047 int ret;
Jason Evans3c234352010-01-27 13:10:55 -08001048
Jason Evans7372b152012-02-10 20:22:09 -08001049 if (config_tcache == false)
1050 return (ENOENT);
1051
Jason Evans3c234352010-01-27 13:10:55 -08001052 VOID();
1053
Jason Evansd4be8b72012-03-26 18:54:44 -07001054 tcache_flush();
Jason Evans3c234352010-01-27 13:10:55 -08001055
1056 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001057label_return:
Jason Evans3c234352010-01-27 13:10:55 -08001058 return (ret);
1059}
Jason Evans3c234352010-01-27 13:10:55 -08001060
Jason Evansb267d0f2010-08-13 15:42:29 -07001061static int
1062thread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1063 void *newp, size_t newlen)
1064{
1065 int ret;
1066 unsigned newind, oldind;
1067
Jason Evans01b3fe52012-04-03 09:28:00 -07001068 newind = oldind = choose_arena(NULL)->ind;
Jason Evansa7153a02011-03-14 11:39:49 -07001069 WRITE(newind, unsigned);
1070 READ(oldind, unsigned);
Jason Evansb267d0f2010-08-13 15:42:29 -07001071 if (newind != oldind) {
1072 arena_t *arena;
1073
1074 if (newind >= narenas) {
1075 /* New arena index is out of range. */
1076 ret = EFAULT;
Jason Evansa1ee7832012-04-10 15:07:44 -07001077 goto label_return;
Jason Evansb267d0f2010-08-13 15:42:29 -07001078 }
1079
1080 /* Initialize arena if necessary. */
1081 malloc_mutex_lock(&arenas_lock);
Jason Evanscd9a1342012-03-21 18:33:03 -07001082 if ((arena = arenas[newind]) == NULL && (arena =
1083 arenas_extend(newind)) == NULL) {
1084 malloc_mutex_unlock(&arenas_lock);
Jason Evansb267d0f2010-08-13 15:42:29 -07001085 ret = EAGAIN;
Jason Evansa1ee7832012-04-10 15:07:44 -07001086 goto label_return;
Jason Evansb267d0f2010-08-13 15:42:29 -07001087 }
Jason Evanscd9a1342012-03-21 18:33:03 -07001088 assert(arena == arenas[newind]);
1089 arenas[oldind]->nthreads--;
1090 arenas[newind]->nthreads++;
1091 malloc_mutex_unlock(&arenas_lock);
Jason Evansb267d0f2010-08-13 15:42:29 -07001092
1093 /* Set new arena association. */
Jason Evans7372b152012-02-10 20:22:09 -08001094 if (config_tcache) {
Jason Evanscd9a1342012-03-21 18:33:03 -07001095 tcache_t *tcache;
Jason Evans122449b2012-04-06 00:35:09 -07001096 if ((uintptr_t)(tcache = *tcache_tsd_get()) >
1097 (uintptr_t)TCACHE_STATE_MAX) {
Jason Evanscd9a1342012-03-21 18:33:03 -07001098 tcache_arena_dissociate(tcache);
1099 tcache_arena_associate(tcache, arena);
1100 }
Jason Evans624f2f32010-12-29 12:21:05 -08001101 }
Jason Evanscd9a1342012-03-21 18:33:03 -07001102 arenas_tsd_set(&arena);
Jason Evansb267d0f2010-08-13 15:42:29 -07001103 }
1104
1105 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001106label_return:
Jason Evansb267d0f2010-08-13 15:42:29 -07001107 return (ret);
1108}
Jason Evansb267d0f2010-08-13 15:42:29 -07001109
Jason Evanscd9a1342012-03-21 18:33:03 -07001110CTL_RO_NL_CGEN(config_stats, thread_allocated,
1111 thread_allocated_tsd_get()->allocated, uint64_t)
1112CTL_RO_NL_CGEN(config_stats, thread_allocatedp,
1113 &thread_allocated_tsd_get()->allocated, uint64_t *)
1114CTL_RO_NL_CGEN(config_stats, thread_deallocated,
1115 thread_allocated_tsd_get()->deallocated, uint64_t)
1116CTL_RO_NL_CGEN(config_stats, thread_deallocatedp,
1117 &thread_allocated_tsd_get()->deallocated, uint64_t *)
Jason Evans93443682010-10-20 17:39:18 -07001118
Jason Evans3c234352010-01-27 13:10:55 -08001119/******************************************************************************/
1120
Jason Evans7372b152012-02-10 20:22:09 -08001121CTL_RO_BOOL_CONFIG_GEN(config_debug)
1122CTL_RO_BOOL_CONFIG_GEN(config_dss)
Jason Evans7372b152012-02-10 20:22:09 -08001123CTL_RO_BOOL_CONFIG_GEN(config_fill)
1124CTL_RO_BOOL_CONFIG_GEN(config_lazy_lock)
Jason Evans59ae2762012-04-16 17:52:27 -07001125CTL_RO_BOOL_CONFIG_GEN(config_munmap)
Jason Evans7372b152012-02-10 20:22:09 -08001126CTL_RO_BOOL_CONFIG_GEN(config_prof)
1127CTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc)
1128CTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind)
1129CTL_RO_BOOL_CONFIG_GEN(config_stats)
Jason Evans7372b152012-02-10 20:22:09 -08001130CTL_RO_BOOL_CONFIG_GEN(config_tcache)
Jason Evans7372b152012-02-10 20:22:09 -08001131CTL_RO_BOOL_CONFIG_GEN(config_tls)
Jason Evansb1476112012-04-05 13:36:17 -07001132CTL_RO_BOOL_CONFIG_GEN(config_utrace)
Jason Evans122449b2012-04-06 00:35:09 -07001133CTL_RO_BOOL_CONFIG_GEN(config_valgrind)
Jason Evans7372b152012-02-10 20:22:09 -08001134CTL_RO_BOOL_CONFIG_GEN(config_xmalloc)
Jason Evans3c234352010-01-27 13:10:55 -08001135
1136/******************************************************************************/
1137
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001138CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001139CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
1140CTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t)
1141CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
1142CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
Jason Evans7372b152012-02-10 20:22:09 -08001143CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool)
1144CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
Jason Evans122449b2012-04-06 00:35:09 -07001145CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
1146CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
Jason Evansb1476112012-04-05 13:36:17 -07001147CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
Jason Evans122449b2012-04-06 00:35:09 -07001148CTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool)
Jason Evans7372b152012-02-10 20:22:09 -08001149CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
1150CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
Jason Evansf3ca7c82012-04-04 16:16:09 -07001151CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
Jason Evans7372b152012-02-10 20:22:09 -08001152CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
1153CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
1154CTL_RO_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) /* Mutable. */
Jason Evans7372b152012-02-10 20:22:09 -08001155CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
1156CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
1157CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
Jason Evans0b25fe72012-04-17 16:39:33 -07001158CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
Jason Evans7372b152012-02-10 20:22:09 -08001159CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
1160CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
Jason Evans3c234352010-01-27 13:10:55 -08001161
1162/******************************************************************************/
1163
Jason Evans49f7e8f2011-03-15 13:59:15 -07001164CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)
1165CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)
1166CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)
Mike Hommey461ad5c2012-04-20 08:38:42 +02001167const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001168arenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)
1169{
1170
Jason Evansb1726102012-02-28 16:50:47 -08001171 if (i > NBINS)
Jason Evans3c234352010-01-27 13:10:55 -08001172 return (NULL);
1173 return (super_arenas_bin_i_node);
1174}
1175
Jason Evansae4c7b42012-04-02 07:04:34 -07001176CTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t)
Mike Hommey461ad5c2012-04-20 08:38:42 +02001177const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001178arenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)
1179{
1180
1181 if (i > nlclasses)
1182 return (NULL);
1183 return (super_arenas_lrun_i_node);
1184}
1185
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001186CTL_RO_NL_GEN(arenas_narenas, narenas, unsigned)
Jason Evans3c234352010-01-27 13:10:55 -08001187
1188static int
1189arenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,
1190 size_t *oldlenp, void *newp, size_t newlen)
1191{
1192 int ret;
1193 unsigned nread, i;
1194
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001195 malloc_mutex_lock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -08001196 READONLY();
1197 if (*oldlenp != narenas * sizeof(bool)) {
1198 ret = EINVAL;
1199 nread = (*oldlenp < narenas * sizeof(bool))
1200 ? (*oldlenp / sizeof(bool)) : narenas;
1201 } else {
1202 ret = 0;
1203 nread = narenas;
1204 }
1205
1206 for (i = 0; i < nread; i++)
1207 ((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
1208
Jason Evansa1ee7832012-04-10 15:07:44 -07001209label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001210 malloc_mutex_unlock(&ctl_mtx);
Jason Evans3c234352010-01-27 13:10:55 -08001211 return (ret);
1212}
1213
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001214CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
Jason Evansae4c7b42012-04-02 07:04:34 -07001215CTL_RO_NL_GEN(arenas_page, PAGE, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001216CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)
Jason Evansb1726102012-02-28 16:50:47 -08001217CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)
Jason Evans7372b152012-02-10 20:22:09 -08001218CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001219CTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t)
Jason Evans3c234352010-01-27 13:10:55 -08001220
Jason Evans6005f072010-09-30 16:55:08 -07001221static int
1222arenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1223 void *newp, size_t newlen)
1224{
1225 int ret;
1226 unsigned arena;
1227
1228 WRITEONLY();
1229 arena = UINT_MAX;
1230 WRITE(arena, unsigned);
1231 if (newp != NULL && arena >= narenas) {
1232 ret = EFAULT;
Jason Evansa1ee7832012-04-10 15:07:44 -07001233 goto label_return;
Jason Evans6005f072010-09-30 16:55:08 -07001234 } else {
1235 arena_t *tarenas[narenas];
1236
1237 malloc_mutex_lock(&arenas_lock);
1238 memcpy(tarenas, arenas, sizeof(arena_t *) * narenas);
1239 malloc_mutex_unlock(&arenas_lock);
1240
1241 if (arena == UINT_MAX) {
Jason Evans1506a1b2010-10-07 08:52:32 -07001242 unsigned i;
1243 for (i = 0; i < narenas; i++) {
Jason Evans6005f072010-09-30 16:55:08 -07001244 if (tarenas[i] != NULL)
1245 arena_purge_all(tarenas[i]);
1246 }
1247 } else {
1248 assert(arena < narenas);
1249 if (tarenas[arena] != NULL)
1250 arena_purge_all(tarenas[arena]);
1251 }
1252 }
1253
1254 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001255label_return:
Jason Evans6005f072010-09-30 16:55:08 -07001256 return (ret);
1257}
1258
Jason Evans3c234352010-01-27 13:10:55 -08001259/******************************************************************************/
1260
Jason Evansd34f9e72010-02-11 13:19:21 -08001261static int
Jason Evansf18c9822010-03-31 18:43:24 -07001262prof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1263 void *newp, size_t newlen)
1264{
1265 int ret;
1266 bool oldval;
1267
Jason Evans7372b152012-02-10 20:22:09 -08001268 if (config_prof == false)
1269 return (ENOENT);
1270
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001271 malloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */
Jason Evansf18c9822010-03-31 18:43:24 -07001272 oldval = opt_prof_active;
1273 if (newp != NULL) {
1274 /*
1275 * The memory barriers will tend to make opt_prof_active
1276 * propagate faster on systems with weak memory ordering.
1277 */
1278 mb_write();
1279 WRITE(opt_prof_active, bool);
1280 mb_write();
1281 }
1282 READ(oldval, bool);
1283
1284 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001285label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001286 malloc_mutex_unlock(&ctl_mtx);
Jason Evansf18c9822010-03-31 18:43:24 -07001287 return (ret);
1288}
1289
1290static int
Jason Evansd34f9e72010-02-11 13:19:21 -08001291prof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1292 void *newp, size_t newlen)
1293{
1294 int ret;
Jason Evans22ca8552010-03-02 11:57:30 -08001295 const char *filename = NULL;
Jason Evansd34f9e72010-02-11 13:19:21 -08001296
Jason Evans7372b152012-02-10 20:22:09 -08001297 if (config_prof == false)
1298 return (ENOENT);
1299
Jason Evans22ca8552010-03-02 11:57:30 -08001300 WRITEONLY();
1301 WRITE(filename, const char *);
Jason Evansd34f9e72010-02-11 13:19:21 -08001302
Jason Evans22ca8552010-03-02 11:57:30 -08001303 if (prof_mdump(filename)) {
1304 ret = EFAULT;
Jason Evansa1ee7832012-04-10 15:07:44 -07001305 goto label_return;
Jason Evans22ca8552010-03-02 11:57:30 -08001306 }
Jason Evansd34f9e72010-02-11 13:19:21 -08001307
1308 ret = 0;
Jason Evansa1ee7832012-04-10 15:07:44 -07001309label_return:
Jason Evansd34f9e72010-02-11 13:19:21 -08001310 return (ret);
1311}
1312
Jason Evans7372b152012-02-10 20:22:09 -08001313CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
Jason Evansd34f9e72010-02-11 13:19:21 -08001314
1315/******************************************************************************/
1316
Jason Evans7372b152012-02-10 20:22:09 -08001317CTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current,
1318 size_t)
1319CTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t)
1320CTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t)
1321CTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t)
1322CTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t)
1323CTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t)
1324CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
Jason Evans86815df2010-03-13 20:32:56 -08001325 ctl_stats.arenas[mib[2]].allocated_small, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001326CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
Jason Evans86815df2010-03-13 20:32:56 -08001327 ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001328CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
Jason Evans86815df2010-03-13 20:32:56 -08001329 ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001330CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
Jason Evans86815df2010-03-13 20:32:56 -08001331 ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001332CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
Jason Evans3c234352010-01-27 13:10:55 -08001333 ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001334CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
Jason Evans3c234352010-01-27 13:10:55 -08001335 ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001336CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
Jason Evans3c234352010-01-27 13:10:55 -08001337 ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001338CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
Jason Evansdafde142010-03-17 16:27:39 -07001339 ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)
Jason Evans3c234352010-01-27 13:10:55 -08001340
Jason Evans7372b152012-02-10 20:22:09 -08001341CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated,
Jason Evans86815df2010-03-13 20:32:56 -08001342 ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001343CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
Jason Evans86815df2010-03-13 20:32:56 -08001344 ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001345CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
Jason Evans86815df2010-03-13 20:32:56 -08001346 ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001347CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
Jason Evans3c234352010-01-27 13:10:55 -08001348 ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001349CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,
Jason Evans3c234352010-01-27 13:10:55 -08001350 ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001351CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,
Jason Evans3c234352010-01-27 13:10:55 -08001352 ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001353CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,
Jason Evans3c234352010-01-27 13:10:55 -08001354 ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001355CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,
Jason Evans3c234352010-01-27 13:10:55 -08001356 ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001357CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,
Jason Evans3c234352010-01-27 13:10:55 -08001358 ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)
1359
Mike Hommey461ad5c2012-04-20 08:38:42 +02001360const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001361stats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j)
1362{
1363
Jason Evansb1726102012-02-28 16:50:47 -08001364 if (j > NBINS)
Jason Evans3c234352010-01-27 13:10:55 -08001365 return (NULL);
1366 return (super_stats_arenas_i_bins_j_node);
1367}
1368
Jason Evans7372b152012-02-10 20:22:09 -08001369CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,
Jason Evansdafde142010-03-17 16:27:39 -07001370 ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001371CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,
Jason Evansdafde142010-03-17 16:27:39 -07001372 ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001373CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,
Jason Evans3c234352010-01-27 13:10:55 -08001374 ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)
Jason Evans7372b152012-02-10 20:22:09 -08001375CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,
Jason Evans3c234352010-01-27 13:10:55 -08001376 ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)
Jason Evans3c234352010-01-27 13:10:55 -08001377
Mike Hommey461ad5c2012-04-20 08:38:42 +02001378const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001379stats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j)
1380{
1381
1382 if (j > nlclasses)
1383 return (NULL);
1384 return (super_stats_arenas_i_lruns_j_node);
1385}
1386
Jason Evans597632b2011-03-18 13:41:33 -07001387CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)
Jason Evans3c234352010-01-27 13:10:55 -08001388CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
1389CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
Jason Evans7372b152012-02-10 20:22:09 -08001390CTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
1391 ctl_stats.arenas[mib[2]].astats.mapped, size_t)
1392CTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
1393 ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
1394CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
1395 ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)
1396CTL_RO_CGEN(config_stats, stats_arenas_i_purged,
1397 ctl_stats.arenas[mib[2]].astats.purged, uint64_t)
Jason Evans3c234352010-01-27 13:10:55 -08001398
Mike Hommey461ad5c2012-04-20 08:38:42 +02001399const ctl_named_node_t *
Jason Evans3c234352010-01-27 13:10:55 -08001400stats_arenas_i_index(const size_t *mib, size_t miblen, size_t i)
1401{
Mike Hommey461ad5c2012-04-20 08:38:42 +02001402 const ctl_named_node_t * ret;
Jason Evans3c234352010-01-27 13:10:55 -08001403
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001404 malloc_mutex_lock(&ctl_mtx);
1405 if (ctl_stats.arenas[i].initialized == false) {
1406 ret = NULL;
Jason Evansa1ee7832012-04-10 15:07:44 -07001407 goto label_return;
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001408 }
1409
1410 ret = super_stats_arenas_i_node;
Jason Evansa1ee7832012-04-10 15:07:44 -07001411label_return:
Jason Evansfc4dcfa2010-11-24 15:44:21 -08001412 malloc_mutex_unlock(&ctl_mtx);
1413 return (ret);
Jason Evans3c234352010-01-27 13:10:55 -08001414}
1415
Jason Evans7372b152012-02-10 20:22:09 -08001416CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)
1417CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)
1418CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
1419CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)