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