ctl.c revision 296221
1234370Sjasone#define	JEMALLOC_CTL_C_
2234370Sjasone#include "jemalloc/internal/jemalloc_internal.h"
3234370Sjasone
4234370Sjasone/******************************************************************************/
5234370Sjasone/* Data. */
6234370Sjasone
7234370Sjasone/*
8234370Sjasone * ctl_mtx protects the following:
9234370Sjasone * - ctl_stats.*
10234370Sjasone */
11234370Sjasonestatic malloc_mutex_t	ctl_mtx;
12234370Sjasonestatic bool		ctl_initialized;
13234370Sjasonestatic uint64_t		ctl_epoch;
14234370Sjasonestatic ctl_stats_t	ctl_stats;
15234370Sjasone
16234370Sjasone/******************************************************************************/
17235238Sjasone/* Helpers for named and indexed nodes. */
18235238Sjasone
19286866SjasoneJEMALLOC_INLINE_C const ctl_named_node_t *
20235238Sjasonectl_named_node(const ctl_node_t *node)
21235238Sjasone{
22235238Sjasone
23235238Sjasone	return ((node->named) ? (const ctl_named_node_t *)node : NULL);
24235238Sjasone}
25235238Sjasone
26286866SjasoneJEMALLOC_INLINE_C const ctl_named_node_t *
27296221Sjasonectl_named_children(const ctl_named_node_t *node, size_t index)
28235238Sjasone{
29235238Sjasone	const ctl_named_node_t *children = ctl_named_node(node->children);
30235238Sjasone
31235238Sjasone	return (children ? &children[index] : NULL);
32235238Sjasone}
33235238Sjasone
34286866SjasoneJEMALLOC_INLINE_C const ctl_indexed_node_t *
35235238Sjasonectl_indexed_node(const ctl_node_t *node)
36235238Sjasone{
37235238Sjasone
38286866Sjasone	return (!node->named ? (const ctl_indexed_node_t *)node : NULL);
39235238Sjasone}
40235238Sjasone
41235238Sjasone/******************************************************************************/
42234370Sjasone/* Function prototypes for non-inline static functions. */
43234370Sjasone
44234370Sjasone#define	CTL_PROTO(n)							\
45234370Sjasonestatic int	n##_ctl(const size_t *mib, size_t miblen, void *oldp,	\
46234370Sjasone    size_t *oldlenp, void *newp, size_t newlen);
47234370Sjasone
48234370Sjasone#define	INDEX_PROTO(n)							\
49242844Sjasonestatic const ctl_named_node_t	*n##_index(const size_t *mib,		\
50242844Sjasone    size_t miblen, size_t i);
51234370Sjasone
52234370Sjasonestatic bool	ctl_arena_init(ctl_arena_stats_t *astats);
53234370Sjasonestatic void	ctl_arena_clear(ctl_arena_stats_t *astats);
54234370Sjasonestatic void	ctl_arena_stats_amerge(ctl_arena_stats_t *cstats,
55234370Sjasone    arena_t *arena);
56234370Sjasonestatic void	ctl_arena_stats_smerge(ctl_arena_stats_t *sstats,
57234370Sjasone    ctl_arena_stats_t *astats);
58234370Sjasonestatic void	ctl_arena_refresh(arena_t *arena, unsigned i);
59242844Sjasonestatic bool	ctl_grow(void);
60234370Sjasonestatic void	ctl_refresh(void);
61234370Sjasonestatic bool	ctl_init(void);
62234370Sjasonestatic int	ctl_lookup(const char *name, ctl_node_t const **nodesp,
63234370Sjasone    size_t *mibp, size_t *depthp);
64234370Sjasone
65234370SjasoneCTL_PROTO(version)
66234370SjasoneCTL_PROTO(epoch)
67234370SjasoneCTL_PROTO(thread_tcache_enabled)
68234370SjasoneCTL_PROTO(thread_tcache_flush)
69286866SjasoneCTL_PROTO(thread_prof_name)
70286866SjasoneCTL_PROTO(thread_prof_active)
71234370SjasoneCTL_PROTO(thread_arena)
72234370SjasoneCTL_PROTO(thread_allocated)
73234370SjasoneCTL_PROTO(thread_allocatedp)
74234370SjasoneCTL_PROTO(thread_deallocated)
75234370SjasoneCTL_PROTO(thread_deallocatedp)
76286866SjasoneCTL_PROTO(config_cache_oblivious)
77234370SjasoneCTL_PROTO(config_debug)
78234370SjasoneCTL_PROTO(config_fill)
79234370SjasoneCTL_PROTO(config_lazy_lock)
80296221SjasoneCTL_PROTO(config_malloc_conf)
81234370SjasoneCTL_PROTO(config_munmap)
82234370SjasoneCTL_PROTO(config_prof)
83234370SjasoneCTL_PROTO(config_prof_libgcc)
84234370SjasoneCTL_PROTO(config_prof_libunwind)
85234370SjasoneCTL_PROTO(config_stats)
86234370SjasoneCTL_PROTO(config_tcache)
87234370SjasoneCTL_PROTO(config_tls)
88234370SjasoneCTL_PROTO(config_utrace)
89234370SjasoneCTL_PROTO(config_valgrind)
90234370SjasoneCTL_PROTO(config_xmalloc)
91234370SjasoneCTL_PROTO(opt_abort)
92242844SjasoneCTL_PROTO(opt_dss)
93234370SjasoneCTL_PROTO(opt_lg_chunk)
94234370SjasoneCTL_PROTO(opt_narenas)
95296221SjasoneCTL_PROTO(opt_purge)
96234370SjasoneCTL_PROTO(opt_lg_dirty_mult)
97296221SjasoneCTL_PROTO(opt_decay_time)
98234370SjasoneCTL_PROTO(opt_stats_print)
99234370SjasoneCTL_PROTO(opt_junk)
100234370SjasoneCTL_PROTO(opt_zero)
101234370SjasoneCTL_PROTO(opt_quarantine)
102234370SjasoneCTL_PROTO(opt_redzone)
103234370SjasoneCTL_PROTO(opt_utrace)
104234370SjasoneCTL_PROTO(opt_xmalloc)
105234370SjasoneCTL_PROTO(opt_tcache)
106234370SjasoneCTL_PROTO(opt_lg_tcache_max)
107234370SjasoneCTL_PROTO(opt_prof)
108234370SjasoneCTL_PROTO(opt_prof_prefix)
109234370SjasoneCTL_PROTO(opt_prof_active)
110286866SjasoneCTL_PROTO(opt_prof_thread_active_init)
111234370SjasoneCTL_PROTO(opt_lg_prof_sample)
112234370SjasoneCTL_PROTO(opt_lg_prof_interval)
113234370SjasoneCTL_PROTO(opt_prof_gdump)
114234543SjasoneCTL_PROTO(opt_prof_final)
115234370SjasoneCTL_PROTO(opt_prof_leak)
116234370SjasoneCTL_PROTO(opt_prof_accum)
117286866SjasoneCTL_PROTO(tcache_create)
118286866SjasoneCTL_PROTO(tcache_flush)
119286866SjasoneCTL_PROTO(tcache_destroy)
120296221Sjasonestatic void	arena_i_purge(unsigned arena_ind, bool all);
121242844SjasoneCTL_PROTO(arena_i_purge)
122296221SjasoneCTL_PROTO(arena_i_decay)
123242844SjasoneCTL_PROTO(arena_i_dss)
124286866SjasoneCTL_PROTO(arena_i_lg_dirty_mult)
125296221SjasoneCTL_PROTO(arena_i_decay_time)
126286866SjasoneCTL_PROTO(arena_i_chunk_hooks)
127242844SjasoneINDEX_PROTO(arena_i)
128234370SjasoneCTL_PROTO(arenas_bin_i_size)
129234370SjasoneCTL_PROTO(arenas_bin_i_nregs)
130234370SjasoneCTL_PROTO(arenas_bin_i_run_size)
131234370SjasoneINDEX_PROTO(arenas_bin_i)
132234370SjasoneCTL_PROTO(arenas_lrun_i_size)
133234370SjasoneINDEX_PROTO(arenas_lrun_i)
134286866SjasoneCTL_PROTO(arenas_hchunk_i_size)
135286866SjasoneINDEX_PROTO(arenas_hchunk_i)
136234370SjasoneCTL_PROTO(arenas_narenas)
137234370SjasoneCTL_PROTO(arenas_initialized)
138286866SjasoneCTL_PROTO(arenas_lg_dirty_mult)
139296221SjasoneCTL_PROTO(arenas_decay_time)
140234370SjasoneCTL_PROTO(arenas_quantum)
141234370SjasoneCTL_PROTO(arenas_page)
142234370SjasoneCTL_PROTO(arenas_tcache_max)
143234370SjasoneCTL_PROTO(arenas_nbins)
144234370SjasoneCTL_PROTO(arenas_nhbins)
145234370SjasoneCTL_PROTO(arenas_nlruns)
146286866SjasoneCTL_PROTO(arenas_nhchunks)
147242844SjasoneCTL_PROTO(arenas_extend)
148286866SjasoneCTL_PROTO(prof_thread_active_init)
149234370SjasoneCTL_PROTO(prof_active)
150234370SjasoneCTL_PROTO(prof_dump)
151286866SjasoneCTL_PROTO(prof_gdump)
152286866SjasoneCTL_PROTO(prof_reset)
153234370SjasoneCTL_PROTO(prof_interval)
154286866SjasoneCTL_PROTO(lg_prof_sample)
155234370SjasoneCTL_PROTO(stats_arenas_i_small_allocated)
156234370SjasoneCTL_PROTO(stats_arenas_i_small_nmalloc)
157234370SjasoneCTL_PROTO(stats_arenas_i_small_ndalloc)
158234370SjasoneCTL_PROTO(stats_arenas_i_small_nrequests)
159234370SjasoneCTL_PROTO(stats_arenas_i_large_allocated)
160234370SjasoneCTL_PROTO(stats_arenas_i_large_nmalloc)
161234370SjasoneCTL_PROTO(stats_arenas_i_large_ndalloc)
162234370SjasoneCTL_PROTO(stats_arenas_i_large_nrequests)
163286866SjasoneCTL_PROTO(stats_arenas_i_huge_allocated)
164286866SjasoneCTL_PROTO(stats_arenas_i_huge_nmalloc)
165286866SjasoneCTL_PROTO(stats_arenas_i_huge_ndalloc)
166286866SjasoneCTL_PROTO(stats_arenas_i_huge_nrequests)
167234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nmalloc)
168234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_ndalloc)
169234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nrequests)
170286866SjasoneCTL_PROTO(stats_arenas_i_bins_j_curregs)
171234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nfills)
172234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nflushes)
173234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nruns)
174234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nreruns)
175234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_curruns)
176234370SjasoneINDEX_PROTO(stats_arenas_i_bins_j)
177234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_nmalloc)
178234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_ndalloc)
179234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_nrequests)
180234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_curruns)
181234370SjasoneINDEX_PROTO(stats_arenas_i_lruns_j)
182286866SjasoneCTL_PROTO(stats_arenas_i_hchunks_j_nmalloc)
183286866SjasoneCTL_PROTO(stats_arenas_i_hchunks_j_ndalloc)
184286866SjasoneCTL_PROTO(stats_arenas_i_hchunks_j_nrequests)
185286866SjasoneCTL_PROTO(stats_arenas_i_hchunks_j_curhchunks)
186286866SjasoneINDEX_PROTO(stats_arenas_i_hchunks_j)
187234370SjasoneCTL_PROTO(stats_arenas_i_nthreads)
188242844SjasoneCTL_PROTO(stats_arenas_i_dss)
189286866SjasoneCTL_PROTO(stats_arenas_i_lg_dirty_mult)
190296221SjasoneCTL_PROTO(stats_arenas_i_decay_time)
191234370SjasoneCTL_PROTO(stats_arenas_i_pactive)
192234370SjasoneCTL_PROTO(stats_arenas_i_pdirty)
193234370SjasoneCTL_PROTO(stats_arenas_i_mapped)
194234370SjasoneCTL_PROTO(stats_arenas_i_npurge)
195234370SjasoneCTL_PROTO(stats_arenas_i_nmadvise)
196234370SjasoneCTL_PROTO(stats_arenas_i_purged)
197286866SjasoneCTL_PROTO(stats_arenas_i_metadata_mapped)
198286866SjasoneCTL_PROTO(stats_arenas_i_metadata_allocated)
199234370SjasoneINDEX_PROTO(stats_arenas_i)
200234370SjasoneCTL_PROTO(stats_cactive)
201234370SjasoneCTL_PROTO(stats_allocated)
202234370SjasoneCTL_PROTO(stats_active)
203286866SjasoneCTL_PROTO(stats_metadata)
204286866SjasoneCTL_PROTO(stats_resident)
205234370SjasoneCTL_PROTO(stats_mapped)
206234370Sjasone
207234370Sjasone/******************************************************************************/
208234370Sjasone/* mallctl tree. */
209234370Sjasone
210234370Sjasone/* Maximum tree depth. */
211234370Sjasone#define	CTL_MAX_DEPTH	6
212234370Sjasone
213235238Sjasone#define	NAME(n)	{true},	n
214235238Sjasone#define	CHILD(t, c)							\
215235238Sjasone	sizeof(c##_node) / sizeof(ctl_##t##_node_t),			\
216235238Sjasone	(ctl_node_t *)c##_node,						\
217235238Sjasone	NULL
218235238Sjasone#define	CTL(c)	0, NULL, c##_ctl
219234370Sjasone
220234370Sjasone/*
221234370Sjasone * Only handles internal indexed nodes, since there are currently no external
222234370Sjasone * ones.
223234370Sjasone */
224235238Sjasone#define	INDEX(i)	{false},	i##_index
225234370Sjasone
226286866Sjasonestatic const ctl_named_node_t	thread_tcache_node[] = {
227234370Sjasone	{NAME("enabled"),	CTL(thread_tcache_enabled)},
228234370Sjasone	{NAME("flush"),		CTL(thread_tcache_flush)}
229234370Sjasone};
230234370Sjasone
231286866Sjasonestatic const ctl_named_node_t	thread_prof_node[] = {
232286866Sjasone	{NAME("name"),		CTL(thread_prof_name)},
233286866Sjasone	{NAME("active"),	CTL(thread_prof_active)}
234286866Sjasone};
235286866Sjasone
236235238Sjasonestatic const ctl_named_node_t	thread_node[] = {
237234370Sjasone	{NAME("arena"),		CTL(thread_arena)},
238234370Sjasone	{NAME("allocated"),	CTL(thread_allocated)},
239234370Sjasone	{NAME("allocatedp"),	CTL(thread_allocatedp)},
240234370Sjasone	{NAME("deallocated"),	CTL(thread_deallocated)},
241234370Sjasone	{NAME("deallocatedp"),	CTL(thread_deallocatedp)},
242286866Sjasone	{NAME("tcache"),	CHILD(named, thread_tcache)},
243286866Sjasone	{NAME("prof"),		CHILD(named, thread_prof)}
244234370Sjasone};
245234370Sjasone
246235238Sjasonestatic const ctl_named_node_t	config_node[] = {
247286866Sjasone	{NAME("cache_oblivious"), CTL(config_cache_oblivious)},
248286866Sjasone	{NAME("debug"),		CTL(config_debug)},
249286866Sjasone	{NAME("fill"),		CTL(config_fill)},
250286866Sjasone	{NAME("lazy_lock"),	CTL(config_lazy_lock)},
251296221Sjasone	{NAME("malloc_conf"),	CTL(config_malloc_conf)},
252286866Sjasone	{NAME("munmap"),	CTL(config_munmap)},
253286866Sjasone	{NAME("prof"),		CTL(config_prof)},
254286866Sjasone	{NAME("prof_libgcc"),	CTL(config_prof_libgcc)},
255286866Sjasone	{NAME("prof_libunwind"), CTL(config_prof_libunwind)},
256286866Sjasone	{NAME("stats"),		CTL(config_stats)},
257286866Sjasone	{NAME("tcache"),	CTL(config_tcache)},
258286866Sjasone	{NAME("tls"),		CTL(config_tls)},
259286866Sjasone	{NAME("utrace"),	CTL(config_utrace)},
260286866Sjasone	{NAME("valgrind"),	CTL(config_valgrind)},
261286866Sjasone	{NAME("xmalloc"),	CTL(config_xmalloc)}
262234370Sjasone};
263234370Sjasone
264235238Sjasonestatic const ctl_named_node_t opt_node[] = {
265286866Sjasone	{NAME("abort"),		CTL(opt_abort)},
266286866Sjasone	{NAME("dss"),		CTL(opt_dss)},
267286866Sjasone	{NAME("lg_chunk"),	CTL(opt_lg_chunk)},
268286866Sjasone	{NAME("narenas"),	CTL(opt_narenas)},
269296221Sjasone	{NAME("purge"),		CTL(opt_purge)},
270286866Sjasone	{NAME("lg_dirty_mult"),	CTL(opt_lg_dirty_mult)},
271296221Sjasone	{NAME("decay_time"),	CTL(opt_decay_time)},
272286866Sjasone	{NAME("stats_print"),	CTL(opt_stats_print)},
273286866Sjasone	{NAME("junk"),		CTL(opt_junk)},
274286866Sjasone	{NAME("zero"),		CTL(opt_zero)},
275286866Sjasone	{NAME("quarantine"),	CTL(opt_quarantine)},
276286866Sjasone	{NAME("redzone"),	CTL(opt_redzone)},
277286866Sjasone	{NAME("utrace"),	CTL(opt_utrace)},
278286866Sjasone	{NAME("xmalloc"),	CTL(opt_xmalloc)},
279286866Sjasone	{NAME("tcache"),	CTL(opt_tcache)},
280286866Sjasone	{NAME("lg_tcache_max"),	CTL(opt_lg_tcache_max)},
281286866Sjasone	{NAME("prof"),		CTL(opt_prof)},
282286866Sjasone	{NAME("prof_prefix"),	CTL(opt_prof_prefix)},
283286866Sjasone	{NAME("prof_active"),	CTL(opt_prof_active)},
284286866Sjasone	{NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)},
285286866Sjasone	{NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
286286866Sjasone	{NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
287286866Sjasone	{NAME("prof_gdump"),	CTL(opt_prof_gdump)},
288286866Sjasone	{NAME("prof_final"),	CTL(opt_prof_final)},
289286866Sjasone	{NAME("prof_leak"),	CTL(opt_prof_leak)},
290286866Sjasone	{NAME("prof_accum"),	CTL(opt_prof_accum)}
291234370Sjasone};
292234370Sjasone
293286866Sjasonestatic const ctl_named_node_t	tcache_node[] = {
294286866Sjasone	{NAME("create"),	CTL(tcache_create)},
295286866Sjasone	{NAME("flush"),		CTL(tcache_flush)},
296286866Sjasone	{NAME("destroy"),	CTL(tcache_destroy)}
297286866Sjasone};
298286866Sjasone
299242844Sjasonestatic const ctl_named_node_t arena_i_node[] = {
300286866Sjasone	{NAME("purge"),		CTL(arena_i_purge)},
301296221Sjasone	{NAME("decay"),		CTL(arena_i_decay)},
302286866Sjasone	{NAME("dss"),		CTL(arena_i_dss)},
303286866Sjasone	{NAME("lg_dirty_mult"),	CTL(arena_i_lg_dirty_mult)},
304296221Sjasone	{NAME("decay_time"),	CTL(arena_i_decay_time)},
305286866Sjasone	{NAME("chunk_hooks"),	CTL(arena_i_chunk_hooks)}
306242844Sjasone};
307242844Sjasonestatic const ctl_named_node_t super_arena_i_node[] = {
308286866Sjasone	{NAME(""),		CHILD(named, arena_i)}
309242844Sjasone};
310242844Sjasone
311242844Sjasonestatic const ctl_indexed_node_t arena_node[] = {
312242844Sjasone	{INDEX(arena_i)}
313242844Sjasone};
314242844Sjasone
315235238Sjasonestatic const ctl_named_node_t arenas_bin_i_node[] = {
316286866Sjasone	{NAME("size"),		CTL(arenas_bin_i_size)},
317286866Sjasone	{NAME("nregs"),		CTL(arenas_bin_i_nregs)},
318286866Sjasone	{NAME("run_size"),	CTL(arenas_bin_i_run_size)}
319234370Sjasone};
320235238Sjasonestatic const ctl_named_node_t super_arenas_bin_i_node[] = {
321286866Sjasone	{NAME(""),		CHILD(named, arenas_bin_i)}
322234370Sjasone};
323234370Sjasone
324235238Sjasonestatic const ctl_indexed_node_t arenas_bin_node[] = {
325234370Sjasone	{INDEX(arenas_bin_i)}
326234370Sjasone};
327234370Sjasone
328235238Sjasonestatic const ctl_named_node_t arenas_lrun_i_node[] = {
329286866Sjasone	{NAME("size"),		CTL(arenas_lrun_i_size)}
330234370Sjasone};
331235238Sjasonestatic const ctl_named_node_t super_arenas_lrun_i_node[] = {
332286866Sjasone	{NAME(""),		CHILD(named, arenas_lrun_i)}
333234370Sjasone};
334234370Sjasone
335235238Sjasonestatic const ctl_indexed_node_t arenas_lrun_node[] = {
336234370Sjasone	{INDEX(arenas_lrun_i)}
337234370Sjasone};
338234370Sjasone
339286866Sjasonestatic const ctl_named_node_t arenas_hchunk_i_node[] = {
340286866Sjasone	{NAME("size"),		CTL(arenas_hchunk_i_size)}
341286866Sjasone};
342286866Sjasonestatic const ctl_named_node_t super_arenas_hchunk_i_node[] = {
343286866Sjasone	{NAME(""),		CHILD(named, arenas_hchunk_i)}
344286866Sjasone};
345286866Sjasone
346286866Sjasonestatic const ctl_indexed_node_t arenas_hchunk_node[] = {
347286866Sjasone	{INDEX(arenas_hchunk_i)}
348286866Sjasone};
349286866Sjasone
350235238Sjasonestatic const ctl_named_node_t arenas_node[] = {
351286866Sjasone	{NAME("narenas"),	CTL(arenas_narenas)},
352286866Sjasone	{NAME("initialized"),	CTL(arenas_initialized)},
353286866Sjasone	{NAME("lg_dirty_mult"),	CTL(arenas_lg_dirty_mult)},
354296221Sjasone	{NAME("decay_time"),	CTL(arenas_decay_time)},
355286866Sjasone	{NAME("quantum"),	CTL(arenas_quantum)},
356286866Sjasone	{NAME("page"),		CTL(arenas_page)},
357286866Sjasone	{NAME("tcache_max"),	CTL(arenas_tcache_max)},
358286866Sjasone	{NAME("nbins"),		CTL(arenas_nbins)},
359286866Sjasone	{NAME("nhbins"),	CTL(arenas_nhbins)},
360286866Sjasone	{NAME("bin"),		CHILD(indexed, arenas_bin)},
361286866Sjasone	{NAME("nlruns"),	CTL(arenas_nlruns)},
362286866Sjasone	{NAME("lrun"),		CHILD(indexed, arenas_lrun)},
363286866Sjasone	{NAME("nhchunks"),	CTL(arenas_nhchunks)},
364286866Sjasone	{NAME("hchunk"),	CHILD(indexed, arenas_hchunk)},
365286866Sjasone	{NAME("extend"),	CTL(arenas_extend)}
366234370Sjasone};
367234370Sjasone
368235238Sjasonestatic const ctl_named_node_t	prof_node[] = {
369286866Sjasone	{NAME("thread_active_init"), CTL(prof_thread_active_init)},
370234370Sjasone	{NAME("active"),	CTL(prof_active)},
371234370Sjasone	{NAME("dump"),		CTL(prof_dump)},
372286866Sjasone	{NAME("gdump"),		CTL(prof_gdump)},
373286866Sjasone	{NAME("reset"),		CTL(prof_reset)},
374286866Sjasone	{NAME("interval"),	CTL(prof_interval)},
375286866Sjasone	{NAME("lg_sample"),	CTL(lg_prof_sample)}
376234370Sjasone};
377234370Sjasone
378286866Sjasonestatic const ctl_named_node_t stats_arenas_i_metadata_node[] = {
379286866Sjasone	{NAME("mapped"),	CTL(stats_arenas_i_metadata_mapped)},
380286866Sjasone	{NAME("allocated"),	CTL(stats_arenas_i_metadata_allocated)}
381234370Sjasone};
382234370Sjasone
383235238Sjasonestatic const ctl_named_node_t stats_arenas_i_small_node[] = {
384286866Sjasone	{NAME("allocated"),	CTL(stats_arenas_i_small_allocated)},
385286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_small_nmalloc)},
386286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_small_ndalloc)},
387286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_small_nrequests)}
388234370Sjasone};
389234370Sjasone
390235238Sjasonestatic const ctl_named_node_t stats_arenas_i_large_node[] = {
391286866Sjasone	{NAME("allocated"),	CTL(stats_arenas_i_large_allocated)},
392286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_large_nmalloc)},
393286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_large_ndalloc)},
394286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_large_nrequests)}
395234370Sjasone};
396234370Sjasone
397286866Sjasonestatic const ctl_named_node_t stats_arenas_i_huge_node[] = {
398286866Sjasone	{NAME("allocated"),	CTL(stats_arenas_i_huge_allocated)},
399286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_huge_nmalloc)},
400286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_huge_ndalloc)},
401286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_huge_nrequests)}
402286866Sjasone};
403286866Sjasone
404235238Sjasonestatic const ctl_named_node_t stats_arenas_i_bins_j_node[] = {
405286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_bins_j_nmalloc)},
406286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_bins_j_ndalloc)},
407286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_bins_j_nrequests)},
408286866Sjasone	{NAME("curregs"),	CTL(stats_arenas_i_bins_j_curregs)},
409286866Sjasone	{NAME("nfills"),	CTL(stats_arenas_i_bins_j_nfills)},
410286866Sjasone	{NAME("nflushes"),	CTL(stats_arenas_i_bins_j_nflushes)},
411286866Sjasone	{NAME("nruns"),		CTL(stats_arenas_i_bins_j_nruns)},
412286866Sjasone	{NAME("nreruns"),	CTL(stats_arenas_i_bins_j_nreruns)},
413286866Sjasone	{NAME("curruns"),	CTL(stats_arenas_i_bins_j_curruns)}
414234370Sjasone};
415235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {
416286866Sjasone	{NAME(""),		CHILD(named, stats_arenas_i_bins_j)}
417234370Sjasone};
418234370Sjasone
419235238Sjasonestatic const ctl_indexed_node_t stats_arenas_i_bins_node[] = {
420234370Sjasone	{INDEX(stats_arenas_i_bins_j)}
421234370Sjasone};
422234370Sjasone
423235238Sjasonestatic const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {
424286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_lruns_j_nmalloc)},
425286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_lruns_j_ndalloc)},
426286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_lruns_j_nrequests)},
427286866Sjasone	{NAME("curruns"),	CTL(stats_arenas_i_lruns_j_curruns)}
428234370Sjasone};
429235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {
430286866Sjasone	{NAME(""),		CHILD(named, stats_arenas_i_lruns_j)}
431234370Sjasone};
432234370Sjasone
433235238Sjasonestatic const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {
434234370Sjasone	{INDEX(stats_arenas_i_lruns_j)}
435234370Sjasone};
436234370Sjasone
437286866Sjasonestatic const ctl_named_node_t stats_arenas_i_hchunks_j_node[] = {
438286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_hchunks_j_nmalloc)},
439286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_hchunks_j_ndalloc)},
440286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_hchunks_j_nrequests)},
441286866Sjasone	{NAME("curhchunks"),	CTL(stats_arenas_i_hchunks_j_curhchunks)}
442286866Sjasone};
443286866Sjasonestatic const ctl_named_node_t super_stats_arenas_i_hchunks_j_node[] = {
444286866Sjasone	{NAME(""),		CHILD(named, stats_arenas_i_hchunks_j)}
445286866Sjasone};
446286866Sjasone
447286866Sjasonestatic const ctl_indexed_node_t stats_arenas_i_hchunks_node[] = {
448286866Sjasone	{INDEX(stats_arenas_i_hchunks_j)}
449286866Sjasone};
450286866Sjasone
451235238Sjasonestatic const ctl_named_node_t stats_arenas_i_node[] = {
452286866Sjasone	{NAME("nthreads"),	CTL(stats_arenas_i_nthreads)},
453286866Sjasone	{NAME("dss"),		CTL(stats_arenas_i_dss)},
454286866Sjasone	{NAME("lg_dirty_mult"),	CTL(stats_arenas_i_lg_dirty_mult)},
455296221Sjasone	{NAME("decay_time"),	CTL(stats_arenas_i_decay_time)},
456286866Sjasone	{NAME("pactive"),	CTL(stats_arenas_i_pactive)},
457286866Sjasone	{NAME("pdirty"),	CTL(stats_arenas_i_pdirty)},
458286866Sjasone	{NAME("mapped"),	CTL(stats_arenas_i_mapped)},
459286866Sjasone	{NAME("npurge"),	CTL(stats_arenas_i_npurge)},
460286866Sjasone	{NAME("nmadvise"),	CTL(stats_arenas_i_nmadvise)},
461286866Sjasone	{NAME("purged"),	CTL(stats_arenas_i_purged)},
462286866Sjasone	{NAME("metadata"),	CHILD(named, stats_arenas_i_metadata)},
463286866Sjasone	{NAME("small"),		CHILD(named, stats_arenas_i_small)},
464286866Sjasone	{NAME("large"),		CHILD(named, stats_arenas_i_large)},
465286866Sjasone	{NAME("huge"),		CHILD(named, stats_arenas_i_huge)},
466286866Sjasone	{NAME("bins"),		CHILD(indexed, stats_arenas_i_bins)},
467286866Sjasone	{NAME("lruns"),		CHILD(indexed, stats_arenas_i_lruns)},
468286866Sjasone	{NAME("hchunks"),	CHILD(indexed, stats_arenas_i_hchunks)}
469234370Sjasone};
470235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_node[] = {
471286866Sjasone	{NAME(""),		CHILD(named, stats_arenas_i)}
472234370Sjasone};
473234370Sjasone
474235238Sjasonestatic const ctl_indexed_node_t stats_arenas_node[] = {
475234370Sjasone	{INDEX(stats_arenas_i)}
476234370Sjasone};
477234370Sjasone
478235238Sjasonestatic const ctl_named_node_t stats_node[] = {
479286866Sjasone	{NAME("cactive"),	CTL(stats_cactive)},
480286866Sjasone	{NAME("allocated"),	CTL(stats_allocated)},
481286866Sjasone	{NAME("active"),	CTL(stats_active)},
482286866Sjasone	{NAME("metadata"),	CTL(stats_metadata)},
483286866Sjasone	{NAME("resident"),	CTL(stats_resident)},
484286866Sjasone	{NAME("mapped"),	CTL(stats_mapped)},
485286866Sjasone	{NAME("arenas"),	CHILD(indexed, stats_arenas)}
486234370Sjasone};
487234370Sjasone
488235238Sjasonestatic const ctl_named_node_t	root_node[] = {
489234370Sjasone	{NAME("version"),	CTL(version)},
490234370Sjasone	{NAME("epoch"),		CTL(epoch)},
491235238Sjasone	{NAME("thread"),	CHILD(named, thread)},
492235238Sjasone	{NAME("config"),	CHILD(named, config)},
493235238Sjasone	{NAME("opt"),		CHILD(named, opt)},
494286866Sjasone	{NAME("tcache"),	CHILD(named, tcache)},
495242844Sjasone	{NAME("arena"),		CHILD(indexed, arena)},
496235238Sjasone	{NAME("arenas"),	CHILD(named, arenas)},
497235238Sjasone	{NAME("prof"),		CHILD(named, prof)},
498235238Sjasone	{NAME("stats"),		CHILD(named, stats)}
499234370Sjasone};
500235238Sjasonestatic const ctl_named_node_t super_root_node[] = {
501235238Sjasone	{NAME(""),		CHILD(named, root)}
502234370Sjasone};
503234370Sjasone
504234370Sjasone#undef NAME
505234370Sjasone#undef CHILD
506234370Sjasone#undef CTL
507234370Sjasone#undef INDEX
508234370Sjasone
509234370Sjasone/******************************************************************************/
510234370Sjasone
511234370Sjasonestatic bool
512234370Sjasonectl_arena_init(ctl_arena_stats_t *astats)
513234370Sjasone{
514234370Sjasone
515234370Sjasone	if (astats->lstats == NULL) {
516286866Sjasone		astats->lstats = (malloc_large_stats_t *)a0malloc(nlclasses *
517234370Sjasone		    sizeof(malloc_large_stats_t));
518234370Sjasone		if (astats->lstats == NULL)
519234370Sjasone			return (true);
520234370Sjasone	}
521234370Sjasone
522286866Sjasone	if (astats->hstats == NULL) {
523286866Sjasone		astats->hstats = (malloc_huge_stats_t *)a0malloc(nhclasses *
524286866Sjasone		    sizeof(malloc_huge_stats_t));
525286866Sjasone		if (astats->hstats == NULL)
526286866Sjasone			return (true);
527286866Sjasone	}
528286866Sjasone
529234370Sjasone	return (false);
530234370Sjasone}
531234370Sjasone
532234370Sjasonestatic void
533234370Sjasonectl_arena_clear(ctl_arena_stats_t *astats)
534234370Sjasone{
535234370Sjasone
536296221Sjasone	astats->nthreads = 0;
537242844Sjasone	astats->dss = dss_prec_names[dss_prec_limit];
538286866Sjasone	astats->lg_dirty_mult = -1;
539296221Sjasone	astats->decay_time = -1;
540234370Sjasone	astats->pactive = 0;
541234370Sjasone	astats->pdirty = 0;
542234370Sjasone	if (config_stats) {
543234370Sjasone		memset(&astats->astats, 0, sizeof(arena_stats_t));
544234370Sjasone		astats->allocated_small = 0;
545234370Sjasone		astats->nmalloc_small = 0;
546234370Sjasone		astats->ndalloc_small = 0;
547234370Sjasone		astats->nrequests_small = 0;
548234370Sjasone		memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));
549234370Sjasone		memset(astats->lstats, 0, nlclasses *
550234370Sjasone		    sizeof(malloc_large_stats_t));
551286866Sjasone		memset(astats->hstats, 0, nhclasses *
552286866Sjasone		    sizeof(malloc_huge_stats_t));
553234370Sjasone	}
554234370Sjasone}
555234370Sjasone
556234370Sjasonestatic void
557234370Sjasonectl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena)
558234370Sjasone{
559234370Sjasone	unsigned i;
560234370Sjasone
561296221Sjasone	if (config_stats) {
562296221Sjasone		arena_stats_merge(arena, &cstats->nthreads, &cstats->dss,
563296221Sjasone		    &cstats->lg_dirty_mult, &cstats->decay_time,
564296221Sjasone		    &cstats->pactive, &cstats->pdirty, &cstats->astats,
565296221Sjasone		    cstats->bstats, cstats->lstats, cstats->hstats);
566234370Sjasone
567296221Sjasone		for (i = 0; i < NBINS; i++) {
568296221Sjasone			cstats->allocated_small += cstats->bstats[i].curregs *
569296221Sjasone			    index2size(i);
570296221Sjasone			cstats->nmalloc_small += cstats->bstats[i].nmalloc;
571296221Sjasone			cstats->ndalloc_small += cstats->bstats[i].ndalloc;
572296221Sjasone			cstats->nrequests_small += cstats->bstats[i].nrequests;
573296221Sjasone		}
574296221Sjasone	} else {
575296221Sjasone		arena_basic_stats_merge(arena, &cstats->nthreads, &cstats->dss,
576296221Sjasone		    &cstats->lg_dirty_mult, &cstats->decay_time,
577296221Sjasone		    &cstats->pactive, &cstats->pdirty);
578234370Sjasone	}
579234370Sjasone}
580234370Sjasone
581234370Sjasonestatic void
582234370Sjasonectl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)
583234370Sjasone{
584234370Sjasone	unsigned i;
585234370Sjasone
586296221Sjasone	sstats->nthreads += astats->nthreads;
587234370Sjasone	sstats->pactive += astats->pactive;
588234370Sjasone	sstats->pdirty += astats->pdirty;
589234370Sjasone
590296221Sjasone	if (config_stats) {
591296221Sjasone		sstats->astats.mapped += astats->astats.mapped;
592296221Sjasone		sstats->astats.npurge += astats->astats.npurge;
593296221Sjasone		sstats->astats.nmadvise += astats->astats.nmadvise;
594296221Sjasone		sstats->astats.purged += astats->astats.purged;
595234370Sjasone
596296221Sjasone		sstats->astats.metadata_mapped +=
597296221Sjasone		    astats->astats.metadata_mapped;
598296221Sjasone		sstats->astats.metadata_allocated +=
599296221Sjasone		    astats->astats.metadata_allocated;
600286866Sjasone
601296221Sjasone		sstats->allocated_small += astats->allocated_small;
602296221Sjasone		sstats->nmalloc_small += astats->nmalloc_small;
603296221Sjasone		sstats->ndalloc_small += astats->ndalloc_small;
604296221Sjasone		sstats->nrequests_small += astats->nrequests_small;
605234370Sjasone
606296221Sjasone		sstats->astats.allocated_large +=
607296221Sjasone		    astats->astats.allocated_large;
608296221Sjasone		sstats->astats.nmalloc_large += astats->astats.nmalloc_large;
609296221Sjasone		sstats->astats.ndalloc_large += astats->astats.ndalloc_large;
610296221Sjasone		sstats->astats.nrequests_large +=
611296221Sjasone		    astats->astats.nrequests_large;
612234370Sjasone
613296221Sjasone		sstats->astats.allocated_huge += astats->astats.allocated_huge;
614296221Sjasone		sstats->astats.nmalloc_huge += astats->astats.nmalloc_huge;
615296221Sjasone		sstats->astats.ndalloc_huge += astats->astats.ndalloc_huge;
616234370Sjasone
617296221Sjasone		for (i = 0; i < NBINS; i++) {
618296221Sjasone			sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
619296221Sjasone			sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
620296221Sjasone			sstats->bstats[i].nrequests +=
621296221Sjasone			    astats->bstats[i].nrequests;
622296221Sjasone			sstats->bstats[i].curregs += astats->bstats[i].curregs;
623296221Sjasone			if (config_tcache) {
624296221Sjasone				sstats->bstats[i].nfills +=
625296221Sjasone				    astats->bstats[i].nfills;
626296221Sjasone				sstats->bstats[i].nflushes +=
627296221Sjasone				    astats->bstats[i].nflushes;
628296221Sjasone			}
629296221Sjasone			sstats->bstats[i].nruns += astats->bstats[i].nruns;
630296221Sjasone			sstats->bstats[i].reruns += astats->bstats[i].reruns;
631296221Sjasone			sstats->bstats[i].curruns += astats->bstats[i].curruns;
632234370Sjasone		}
633286866Sjasone
634296221Sjasone		for (i = 0; i < nlclasses; i++) {
635296221Sjasone			sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;
636296221Sjasone			sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;
637296221Sjasone			sstats->lstats[i].nrequests +=
638296221Sjasone			    astats->lstats[i].nrequests;
639296221Sjasone			sstats->lstats[i].curruns += astats->lstats[i].curruns;
640296221Sjasone		}
641286866Sjasone
642296221Sjasone		for (i = 0; i < nhclasses; i++) {
643296221Sjasone			sstats->hstats[i].nmalloc += astats->hstats[i].nmalloc;
644296221Sjasone			sstats->hstats[i].ndalloc += astats->hstats[i].ndalloc;
645296221Sjasone			sstats->hstats[i].curhchunks +=
646296221Sjasone			    astats->hstats[i].curhchunks;
647296221Sjasone		}
648286866Sjasone	}
649234370Sjasone}
650234370Sjasone
651234370Sjasonestatic void
652234370Sjasonectl_arena_refresh(arena_t *arena, unsigned i)
653234370Sjasone{
654234370Sjasone	ctl_arena_stats_t *astats = &ctl_stats.arenas[i];
655242844Sjasone	ctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas];
656234370Sjasone
657234370Sjasone	ctl_arena_clear(astats);
658296221Sjasone	ctl_arena_stats_amerge(astats, arena);
659296221Sjasone	/* Merge into sum stats as well. */
660296221Sjasone	ctl_arena_stats_smerge(sstats, astats);
661234370Sjasone}
662234370Sjasone
663242844Sjasonestatic bool
664242844Sjasonectl_grow(void)
665242844Sjasone{
666242844Sjasone	ctl_arena_stats_t *astats;
667242844Sjasone
668286866Sjasone	/* Initialize new arena. */
669286866Sjasone	if (arena_init(ctl_stats.narenas) == NULL)
670286866Sjasone		return (true);
671286866Sjasone
672286866Sjasone	/* Allocate extended arena stats. */
673286866Sjasone	astats = (ctl_arena_stats_t *)a0malloc((ctl_stats.narenas + 2) *
674256823Sjasone	    sizeof(ctl_arena_stats_t));
675256823Sjasone	if (astats == NULL)
676256823Sjasone		return (true);
677242844Sjasone
678256823Sjasone	/* Initialize the new astats element. */
679256823Sjasone	memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) *
680256823Sjasone	    sizeof(ctl_arena_stats_t));
681242844Sjasone	memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t));
682256823Sjasone	if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) {
683286866Sjasone		a0dalloc(astats);
684242844Sjasone		return (true);
685256823Sjasone	}
686242844Sjasone	/* Swap merged stats to their new location. */
687242844Sjasone	{
688242844Sjasone		ctl_arena_stats_t tstats;
689242844Sjasone		memcpy(&tstats, &astats[ctl_stats.narenas],
690242844Sjasone		    sizeof(ctl_arena_stats_t));
691242844Sjasone		memcpy(&astats[ctl_stats.narenas],
692242844Sjasone		    &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t));
693242844Sjasone		memcpy(&astats[ctl_stats.narenas + 1], &tstats,
694242844Sjasone		    sizeof(ctl_arena_stats_t));
695242844Sjasone	}
696286866Sjasone	a0dalloc(ctl_stats.arenas);
697242844Sjasone	ctl_stats.arenas = astats;
698242844Sjasone	ctl_stats.narenas++;
699242844Sjasone
700242844Sjasone	return (false);
701242844Sjasone}
702242844Sjasone
703234370Sjasonestatic void
704234370Sjasonectl_refresh(void)
705234370Sjasone{
706234370Sjasone	unsigned i;
707242844Sjasone	VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);
708234370Sjasone
709234370Sjasone	/*
710234370Sjasone	 * Clear sum stats, since they will be merged into by
711234370Sjasone	 * ctl_arena_refresh().
712234370Sjasone	 */
713242844Sjasone	ctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]);
714234370Sjasone
715296221Sjasone	for (i = 0; i < ctl_stats.narenas; i++)
716296221Sjasone		tarenas[i] = arena_get(i, false);
717286866Sjasone
718242844Sjasone	for (i = 0; i < ctl_stats.narenas; i++) {
719234370Sjasone		bool initialized = (tarenas[i] != NULL);
720234370Sjasone
721234370Sjasone		ctl_stats.arenas[i].initialized = initialized;
722234370Sjasone		if (initialized)
723234370Sjasone			ctl_arena_refresh(tarenas[i], i);
724234370Sjasone	}
725234370Sjasone
726234370Sjasone	if (config_stats) {
727286866Sjasone		size_t base_allocated, base_resident, base_mapped;
728286866Sjasone		base_stats_get(&base_allocated, &base_resident, &base_mapped);
729242844Sjasone		ctl_stats.allocated =
730286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].allocated_small +
731286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large +
732286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_huge;
733242844Sjasone		ctl_stats.active =
734286866Sjasone		    (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE);
735286866Sjasone		ctl_stats.metadata = base_allocated +
736286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +
737286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats
738286866Sjasone		    .metadata_allocated;
739286866Sjasone		ctl_stats.resident = base_resident +
740286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +
741286866Sjasone		    ((ctl_stats.arenas[ctl_stats.narenas].pactive +
742286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].pdirty) << LG_PAGE);
743286866Sjasone		ctl_stats.mapped = base_mapped +
744286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.mapped;
745234370Sjasone	}
746234370Sjasone
747234370Sjasone	ctl_epoch++;
748234370Sjasone}
749234370Sjasone
750234370Sjasonestatic bool
751234370Sjasonectl_init(void)
752234370Sjasone{
753234370Sjasone	bool ret;
754234370Sjasone
755234370Sjasone	malloc_mutex_lock(&ctl_mtx);
756286866Sjasone	if (!ctl_initialized) {
757234370Sjasone		/*
758234370Sjasone		 * Allocate space for one extra arena stats element, which
759234370Sjasone		 * contains summed stats across all arenas.
760234370Sjasone		 */
761286866Sjasone		ctl_stats.narenas = narenas_total_get();
762286866Sjasone		ctl_stats.arenas = (ctl_arena_stats_t *)a0malloc(
763242844Sjasone		    (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t));
764234370Sjasone		if (ctl_stats.arenas == NULL) {
765234370Sjasone			ret = true;
766234370Sjasone			goto label_return;
767234370Sjasone		}
768242844Sjasone		memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) *
769234370Sjasone		    sizeof(ctl_arena_stats_t));
770234370Sjasone
771234370Sjasone		/*
772234370Sjasone		 * Initialize all stats structures, regardless of whether they
773234370Sjasone		 * ever get used.  Lazy initialization would allow errors to
774234370Sjasone		 * cause inconsistent state to be viewable by the application.
775234370Sjasone		 */
776234370Sjasone		if (config_stats) {
777234370Sjasone			unsigned i;
778242844Sjasone			for (i = 0; i <= ctl_stats.narenas; i++) {
779234370Sjasone				if (ctl_arena_init(&ctl_stats.arenas[i])) {
780286866Sjasone					unsigned j;
781286866Sjasone					for (j = 0; j < i; j++) {
782286866Sjasone						a0dalloc(
783286866Sjasone						    ctl_stats.arenas[j].lstats);
784286866Sjasone						a0dalloc(
785286866Sjasone						    ctl_stats.arenas[j].hstats);
786286866Sjasone					}
787286866Sjasone					a0dalloc(ctl_stats.arenas);
788286866Sjasone					ctl_stats.arenas = NULL;
789234370Sjasone					ret = true;
790234370Sjasone					goto label_return;
791234370Sjasone				}
792234370Sjasone			}
793234370Sjasone		}
794242844Sjasone		ctl_stats.arenas[ctl_stats.narenas].initialized = true;
795234370Sjasone
796234370Sjasone		ctl_epoch = 0;
797234370Sjasone		ctl_refresh();
798234370Sjasone		ctl_initialized = true;
799234370Sjasone	}
800234370Sjasone
801234370Sjasone	ret = false;
802234370Sjasonelabel_return:
803234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
804234370Sjasone	return (ret);
805234370Sjasone}
806234370Sjasone
807234370Sjasonestatic int
808234370Sjasonectl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp,
809234370Sjasone    size_t *depthp)
810234370Sjasone{
811234370Sjasone	int ret;
812234370Sjasone	const char *elm, *tdot, *dot;
813234370Sjasone	size_t elen, i, j;
814235238Sjasone	const ctl_named_node_t *node;
815234370Sjasone
816234370Sjasone	elm = name;
817234370Sjasone	/* Equivalent to strchrnul(). */
818234370Sjasone	dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
819234370Sjasone	elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
820234370Sjasone	if (elen == 0) {
821234370Sjasone		ret = ENOENT;
822234370Sjasone		goto label_return;
823234370Sjasone	}
824234370Sjasone	node = super_root_node;
825234370Sjasone	for (i = 0; i < *depthp; i++) {
826235238Sjasone		assert(node);
827235238Sjasone		assert(node->nchildren > 0);
828235238Sjasone		if (ctl_named_node(node->children) != NULL) {
829235238Sjasone			const ctl_named_node_t *pnode = node;
830234370Sjasone
831234370Sjasone			/* Children are named. */
832235238Sjasone			for (j = 0; j < node->nchildren; j++) {
833235238Sjasone				const ctl_named_node_t *child =
834235238Sjasone				    ctl_named_children(node, j);
835235238Sjasone				if (strlen(child->name) == elen &&
836235238Sjasone				    strncmp(elm, child->name, elen) == 0) {
837234370Sjasone					node = child;
838234370Sjasone					if (nodesp != NULL)
839235238Sjasone						nodesp[i] =
840235238Sjasone						    (const ctl_node_t *)node;
841234370Sjasone					mibp[i] = j;
842234370Sjasone					break;
843234370Sjasone				}
844234370Sjasone			}
845234370Sjasone			if (node == pnode) {
846234370Sjasone				ret = ENOENT;
847234370Sjasone				goto label_return;
848234370Sjasone			}
849234370Sjasone		} else {
850234370Sjasone			uintmax_t index;
851235238Sjasone			const ctl_indexed_node_t *inode;
852234370Sjasone
853234370Sjasone			/* Children are indexed. */
854234370Sjasone			index = malloc_strtoumax(elm, NULL, 10);
855234370Sjasone			if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
856234370Sjasone				ret = ENOENT;
857234370Sjasone				goto label_return;
858234370Sjasone			}
859234370Sjasone
860235238Sjasone			inode = ctl_indexed_node(node->children);
861235238Sjasone			node = inode->index(mibp, *depthp, (size_t)index);
862234370Sjasone			if (node == NULL) {
863234370Sjasone				ret = ENOENT;
864234370Sjasone				goto label_return;
865234370Sjasone			}
866234370Sjasone
867234370Sjasone			if (nodesp != NULL)
868235238Sjasone				nodesp[i] = (const ctl_node_t *)node;
869234370Sjasone			mibp[i] = (size_t)index;
870234370Sjasone		}
871234370Sjasone
872234370Sjasone		if (node->ctl != NULL) {
873234370Sjasone			/* Terminal node. */
874234370Sjasone			if (*dot != '\0') {
875234370Sjasone				/*
876234370Sjasone				 * The name contains more elements than are
877234370Sjasone				 * in this path through the tree.
878234370Sjasone				 */
879234370Sjasone				ret = ENOENT;
880234370Sjasone				goto label_return;
881234370Sjasone			}
882234370Sjasone			/* Complete lookup successful. */
883234370Sjasone			*depthp = i + 1;
884234370Sjasone			break;
885234370Sjasone		}
886234370Sjasone
887234370Sjasone		/* Update elm. */
888234370Sjasone		if (*dot == '\0') {
889234370Sjasone			/* No more elements. */
890234370Sjasone			ret = ENOENT;
891234370Sjasone			goto label_return;
892234370Sjasone		}
893234370Sjasone		elm = &dot[1];
894234370Sjasone		dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
895234370Sjasone		    strchr(elm, '\0');
896234370Sjasone		elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
897234370Sjasone	}
898234370Sjasone
899234370Sjasone	ret = 0;
900234370Sjasonelabel_return:
901234370Sjasone	return (ret);
902234370Sjasone}
903234370Sjasone
904234370Sjasoneint
905234370Sjasonectl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,
906234370Sjasone    size_t newlen)
907234370Sjasone{
908234370Sjasone	int ret;
909234370Sjasone	size_t depth;
910234370Sjasone	ctl_node_t const *nodes[CTL_MAX_DEPTH];
911234370Sjasone	size_t mib[CTL_MAX_DEPTH];
912235238Sjasone	const ctl_named_node_t *node;
913234370Sjasone
914286866Sjasone	if (!ctl_initialized && ctl_init()) {
915234370Sjasone		ret = EAGAIN;
916234370Sjasone		goto label_return;
917234370Sjasone	}
918234370Sjasone
919234370Sjasone	depth = CTL_MAX_DEPTH;
920234370Sjasone	ret = ctl_lookup(name, nodes, mib, &depth);
921234370Sjasone	if (ret != 0)
922234370Sjasone		goto label_return;
923234370Sjasone
924235238Sjasone	node = ctl_named_node(nodes[depth-1]);
925235238Sjasone	if (node != NULL && node->ctl)
926235238Sjasone		ret = node->ctl(mib, depth, oldp, oldlenp, newp, newlen);
927235238Sjasone	else {
928234370Sjasone		/* The name refers to a partial path through the ctl tree. */
929234370Sjasone		ret = ENOENT;
930234370Sjasone	}
931234370Sjasone
932234370Sjasonelabel_return:
933234370Sjasone	return(ret);
934234370Sjasone}
935234370Sjasone
936234370Sjasoneint
937234370Sjasonectl_nametomib(const char *name, size_t *mibp, size_t *miblenp)
938234370Sjasone{
939234370Sjasone	int ret;
940234370Sjasone
941286866Sjasone	if (!ctl_initialized && ctl_init()) {
942234370Sjasone		ret = EAGAIN;
943234370Sjasone		goto label_return;
944234370Sjasone	}
945234370Sjasone
946234370Sjasone	ret = ctl_lookup(name, NULL, mibp, miblenp);
947234370Sjasonelabel_return:
948234370Sjasone	return(ret);
949234370Sjasone}
950234370Sjasone
951234370Sjasoneint
952234370Sjasonectl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
953234370Sjasone    void *newp, size_t newlen)
954234370Sjasone{
955234370Sjasone	int ret;
956235238Sjasone	const ctl_named_node_t *node;
957234370Sjasone	size_t i;
958234370Sjasone
959286866Sjasone	if (!ctl_initialized && ctl_init()) {
960234370Sjasone		ret = EAGAIN;
961234370Sjasone		goto label_return;
962234370Sjasone	}
963234370Sjasone
964234370Sjasone	/* Iterate down the tree. */
965234370Sjasone	node = super_root_node;
966234370Sjasone	for (i = 0; i < miblen; i++) {
967235238Sjasone		assert(node);
968235238Sjasone		assert(node->nchildren > 0);
969235238Sjasone		if (ctl_named_node(node->children) != NULL) {
970234370Sjasone			/* Children are named. */
971296221Sjasone			if (node->nchildren <= (unsigned)mib[i]) {
972234370Sjasone				ret = ENOENT;
973234370Sjasone				goto label_return;
974234370Sjasone			}
975235238Sjasone			node = ctl_named_children(node, mib[i]);
976234370Sjasone		} else {
977235238Sjasone			const ctl_indexed_node_t *inode;
978234370Sjasone
979234370Sjasone			/* Indexed element. */
980235238Sjasone			inode = ctl_indexed_node(node->children);
981235238Sjasone			node = inode->index(mib, miblen, mib[i]);
982234370Sjasone			if (node == NULL) {
983234370Sjasone				ret = ENOENT;
984234370Sjasone				goto label_return;
985234370Sjasone			}
986234370Sjasone		}
987234370Sjasone	}
988234370Sjasone
989234370Sjasone	/* Call the ctl function. */
990235238Sjasone	if (node && node->ctl)
991235238Sjasone		ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen);
992235238Sjasone	else {
993234370Sjasone		/* Partial MIB. */
994234370Sjasone		ret = ENOENT;
995234370Sjasone	}
996234370Sjasone
997234370Sjasonelabel_return:
998234370Sjasone	return(ret);
999234370Sjasone}
1000234370Sjasone
1001234370Sjasonebool
1002234370Sjasonectl_boot(void)
1003234370Sjasone{
1004234370Sjasone
1005234370Sjasone	if (malloc_mutex_init(&ctl_mtx))
1006234370Sjasone		return (true);
1007234370Sjasone
1008234370Sjasone	ctl_initialized = false;
1009234370Sjasone
1010234370Sjasone	return (false);
1011234370Sjasone}
1012234370Sjasone
1013242844Sjasonevoid
1014242844Sjasonectl_prefork(void)
1015242844Sjasone{
1016242844Sjasone
1017261071Sjasone	malloc_mutex_prefork(&ctl_mtx);
1018242844Sjasone}
1019242844Sjasone
1020242844Sjasonevoid
1021242844Sjasonectl_postfork_parent(void)
1022242844Sjasone{
1023242844Sjasone
1024242844Sjasone	malloc_mutex_postfork_parent(&ctl_mtx);
1025242844Sjasone}
1026242844Sjasone
1027242844Sjasonevoid
1028242844Sjasonectl_postfork_child(void)
1029242844Sjasone{
1030242844Sjasone
1031242844Sjasone	malloc_mutex_postfork_child(&ctl_mtx);
1032242844Sjasone}
1033242844Sjasone
1034234370Sjasone/******************************************************************************/
1035234370Sjasone/* *_ctl() functions. */
1036234370Sjasone
1037234370Sjasone#define	READONLY()	do {						\
1038234370Sjasone	if (newp != NULL || newlen != 0) {				\
1039234370Sjasone		ret = EPERM;						\
1040235238Sjasone		goto label_return;					\
1041234370Sjasone	}								\
1042234370Sjasone} while (0)
1043234370Sjasone
1044234370Sjasone#define	WRITEONLY()	do {						\
1045234370Sjasone	if (oldp != NULL || oldlenp != NULL) {				\
1046234370Sjasone		ret = EPERM;						\
1047235238Sjasone		goto label_return;					\
1048234370Sjasone	}								\
1049234370Sjasone} while (0)
1050234370Sjasone
1051286866Sjasone#define	READ_XOR_WRITE()	do {					\
1052286866Sjasone	if ((oldp != NULL && oldlenp != NULL) && (newp != NULL ||	\
1053286866Sjasone	    newlen != 0)) {						\
1054286866Sjasone		ret = EPERM;						\
1055286866Sjasone		goto label_return;					\
1056286866Sjasone	}								\
1057286866Sjasone} while (0)
1058286866Sjasone
1059234370Sjasone#define	READ(v, t)	do {						\
1060234370Sjasone	if (oldp != NULL && oldlenp != NULL) {				\
1061234370Sjasone		if (*oldlenp != sizeof(t)) {				\
1062234370Sjasone			size_t	copylen = (sizeof(t) <= *oldlenp)	\
1063234370Sjasone			    ? sizeof(t) : *oldlenp;			\
1064245868Sjasone			memcpy(oldp, (void *)&(v), copylen);		\
1065234370Sjasone			ret = EINVAL;					\
1066235238Sjasone			goto label_return;				\
1067286866Sjasone		}							\
1068286866Sjasone		*(t *)oldp = (v);					\
1069234370Sjasone	}								\
1070234370Sjasone} while (0)
1071234370Sjasone
1072234370Sjasone#define	WRITE(v, t)	do {						\
1073234370Sjasone	if (newp != NULL) {						\
1074234370Sjasone		if (newlen != sizeof(t)) {				\
1075234370Sjasone			ret = EINVAL;					\
1076235238Sjasone			goto label_return;				\
1077234370Sjasone		}							\
1078245868Sjasone		(v) = *(t *)newp;					\
1079234370Sjasone	}								\
1080234370Sjasone} while (0)
1081234370Sjasone
1082234370Sjasone/*
1083234370Sjasone * There's a lot of code duplication in the following macros due to limitations
1084234370Sjasone * in how nested cpp macros are expanded.
1085234370Sjasone */
1086234370Sjasone#define	CTL_RO_CLGEN(c, l, n, v, t)					\
1087234370Sjasonestatic int								\
1088234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
1089234370Sjasone    void *newp, size_t newlen)						\
1090234370Sjasone{									\
1091234370Sjasone	int ret;							\
1092234370Sjasone	t oldval;							\
1093234370Sjasone									\
1094286866Sjasone	if (!(c))							\
1095234370Sjasone		return (ENOENT);					\
1096234370Sjasone	if (l)								\
1097234370Sjasone		malloc_mutex_lock(&ctl_mtx);				\
1098234370Sjasone	READONLY();							\
1099245868Sjasone	oldval = (v);							\
1100234370Sjasone	READ(oldval, t);						\
1101234370Sjasone									\
1102234370Sjasone	ret = 0;							\
1103235238Sjasonelabel_return:								\
1104234370Sjasone	if (l)								\
1105234370Sjasone		malloc_mutex_unlock(&ctl_mtx);				\
1106234370Sjasone	return (ret);							\
1107234370Sjasone}
1108234370Sjasone
1109234370Sjasone#define	CTL_RO_CGEN(c, n, v, t)						\
1110234370Sjasonestatic int								\
1111234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
1112234370Sjasone    void *newp, size_t newlen)						\
1113234370Sjasone{									\
1114234370Sjasone	int ret;							\
1115234370Sjasone	t oldval;							\
1116234370Sjasone									\
1117286866Sjasone	if (!(c))							\
1118234370Sjasone		return (ENOENT);					\
1119234370Sjasone	malloc_mutex_lock(&ctl_mtx);					\
1120234370Sjasone	READONLY();							\
1121245868Sjasone	oldval = (v);							\
1122234370Sjasone	READ(oldval, t);						\
1123234370Sjasone									\
1124234370Sjasone	ret = 0;							\
1125235238Sjasonelabel_return:								\
1126234370Sjasone	malloc_mutex_unlock(&ctl_mtx);					\
1127234370Sjasone	return (ret);							\
1128234370Sjasone}
1129234370Sjasone
1130234370Sjasone#define	CTL_RO_GEN(n, v, t)						\
1131234370Sjasonestatic int								\
1132234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
1133234370Sjasone    void *newp, size_t newlen)						\
1134234370Sjasone{									\
1135234370Sjasone	int ret;							\
1136234370Sjasone	t oldval;							\
1137234370Sjasone									\
1138234370Sjasone	malloc_mutex_lock(&ctl_mtx);					\
1139234370Sjasone	READONLY();							\
1140245868Sjasone	oldval = (v);							\
1141234370Sjasone	READ(oldval, t);						\
1142234370Sjasone									\
1143234370Sjasone	ret = 0;							\
1144235238Sjasonelabel_return:								\
1145234370Sjasone	malloc_mutex_unlock(&ctl_mtx);					\
1146234370Sjasone	return (ret);							\
1147234370Sjasone}
1148234370Sjasone
1149234370Sjasone/*
1150234370Sjasone * ctl_mtx is not acquired, under the assumption that no pertinent data will
1151234370Sjasone * mutate during the call.
1152234370Sjasone */
1153234370Sjasone#define	CTL_RO_NL_CGEN(c, n, v, t)					\
1154234370Sjasonestatic int								\
1155234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
1156234370Sjasone    void *newp, size_t newlen)						\
1157234370Sjasone{									\
1158234370Sjasone	int ret;							\
1159234370Sjasone	t oldval;							\
1160234370Sjasone									\
1161286866Sjasone	if (!(c))							\
1162234370Sjasone		return (ENOENT);					\
1163234370Sjasone	READONLY();							\
1164245868Sjasone	oldval = (v);							\
1165234370Sjasone	READ(oldval, t);						\
1166234370Sjasone									\
1167234370Sjasone	ret = 0;							\
1168235238Sjasonelabel_return:								\
1169234370Sjasone	return (ret);							\
1170234370Sjasone}
1171234370Sjasone
1172234370Sjasone#define	CTL_RO_NL_GEN(n, v, t)						\
1173234370Sjasonestatic int								\
1174234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
1175234370Sjasone    void *newp, size_t newlen)						\
1176234370Sjasone{									\
1177234370Sjasone	int ret;							\
1178234370Sjasone	t oldval;							\
1179234370Sjasone									\
1180234370Sjasone	READONLY();							\
1181245868Sjasone	oldval = (v);							\
1182234370Sjasone	READ(oldval, t);						\
1183234370Sjasone									\
1184234370Sjasone	ret = 0;							\
1185235238Sjasonelabel_return:								\
1186234370Sjasone	return (ret);							\
1187234370Sjasone}
1188234370Sjasone
1189286866Sjasone#define	CTL_TSD_RO_NL_CGEN(c, n, m, t)					\
1190286866Sjasonestatic int								\
1191286866Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
1192286866Sjasone    void *newp, size_t newlen)						\
1193286866Sjasone{									\
1194286866Sjasone	int ret;							\
1195286866Sjasone	t oldval;							\
1196286866Sjasone	tsd_t *tsd;							\
1197286866Sjasone									\
1198286866Sjasone	if (!(c))							\
1199286866Sjasone		return (ENOENT);					\
1200286866Sjasone	READONLY();							\
1201286866Sjasone	tsd = tsd_fetch();						\
1202286866Sjasone	oldval = (m(tsd));						\
1203286866Sjasone	READ(oldval, t);						\
1204286866Sjasone									\
1205286866Sjasone	ret = 0;							\
1206286866Sjasonelabel_return:								\
1207286866Sjasone	return (ret);							\
1208286866Sjasone}
1209286866Sjasone
1210296221Sjasone#define	CTL_RO_CONFIG_GEN(n, t)						\
1211234370Sjasonestatic int								\
1212234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
1213234370Sjasone    void *newp, size_t newlen)						\
1214234370Sjasone{									\
1215234370Sjasone	int ret;							\
1216296221Sjasone	t oldval;							\
1217234370Sjasone									\
1218234370Sjasone	READONLY();							\
1219234370Sjasone	oldval = n;							\
1220296221Sjasone	READ(oldval, t);						\
1221234370Sjasone									\
1222234370Sjasone	ret = 0;							\
1223235238Sjasonelabel_return:								\
1224234370Sjasone	return (ret);							\
1225234370Sjasone}
1226234370Sjasone
1227261071Sjasone/******************************************************************************/
1228261071Sjasone
1229234370SjasoneCTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
1230234370Sjasone
1231234370Sjasonestatic int
1232234370Sjasoneepoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1233234370Sjasone    void *newp, size_t newlen)
1234234370Sjasone{
1235234370Sjasone	int ret;
1236256823Sjasone	UNUSED uint64_t newval;
1237234370Sjasone
1238234370Sjasone	malloc_mutex_lock(&ctl_mtx);
1239234370Sjasone	WRITE(newval, uint64_t);
1240235238Sjasone	if (newp != NULL)
1241234370Sjasone		ctl_refresh();
1242234370Sjasone	READ(ctl_epoch, uint64_t);
1243234370Sjasone
1244234370Sjasone	ret = 0;
1245234370Sjasonelabel_return:
1246234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
1247234370Sjasone	return (ret);
1248234370Sjasone}
1249234370Sjasone
1250261071Sjasone/******************************************************************************/
1251234370Sjasone
1252296221SjasoneCTL_RO_CONFIG_GEN(config_cache_oblivious, bool)
1253296221SjasoneCTL_RO_CONFIG_GEN(config_debug, bool)
1254296221SjasoneCTL_RO_CONFIG_GEN(config_fill, bool)
1255296221SjasoneCTL_RO_CONFIG_GEN(config_lazy_lock, bool)
1256296221SjasoneCTL_RO_CONFIG_GEN(config_malloc_conf, const char *)
1257296221SjasoneCTL_RO_CONFIG_GEN(config_munmap, bool)
1258296221SjasoneCTL_RO_CONFIG_GEN(config_prof, bool)
1259296221SjasoneCTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
1260296221SjasoneCTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
1261296221SjasoneCTL_RO_CONFIG_GEN(config_stats, bool)
1262296221SjasoneCTL_RO_CONFIG_GEN(config_tcache, bool)
1263296221SjasoneCTL_RO_CONFIG_GEN(config_tls, bool)
1264296221SjasoneCTL_RO_CONFIG_GEN(config_utrace, bool)
1265296221SjasoneCTL_RO_CONFIG_GEN(config_valgrind, bool)
1266296221SjasoneCTL_RO_CONFIG_GEN(config_xmalloc, bool)
1267234370Sjasone
1268261071Sjasone/******************************************************************************/
1269234370Sjasone
1270261071SjasoneCTL_RO_NL_GEN(opt_abort, opt_abort, bool)
1271261071SjasoneCTL_RO_NL_GEN(opt_dss, opt_dss, const char *)
1272261071SjasoneCTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
1273296221SjasoneCTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned)
1274296221SjasoneCTL_RO_NL_GEN(opt_purge, purge_mode_names[opt_purge], const char *)
1275261071SjasoneCTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
1276296221SjasoneCTL_RO_NL_GEN(opt_decay_time, opt_decay_time, ssize_t)
1277261071SjasoneCTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
1278286866SjasoneCTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)
1279261071SjasoneCTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
1280261071SjasoneCTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
1281261071SjasoneCTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
1282261071SjasoneCTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
1283261071SjasoneCTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
1284261071SjasoneCTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
1285261071SjasoneCTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
1286261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
1287261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
1288286866SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool)
1289286866SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
1290286866Sjasone    opt_prof_thread_active_init, bool)
1291261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
1292261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
1293261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
1294261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
1295261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
1296261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
1297234370Sjasone
1298261071Sjasone/******************************************************************************/
1299234370Sjasone
1300234370Sjasonestatic int
1301234370Sjasonethread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1302234370Sjasone    void *newp, size_t newlen)
1303234370Sjasone{
1304234370Sjasone	int ret;
1305286866Sjasone	tsd_t *tsd;
1306286866Sjasone	arena_t *oldarena;
1307234370Sjasone	unsigned newind, oldind;
1308234370Sjasone
1309286866Sjasone	tsd = tsd_fetch();
1310286866Sjasone	oldarena = arena_choose(tsd, NULL);
1311286866Sjasone	if (oldarena == NULL)
1312286866Sjasone		return (EAGAIN);
1313286866Sjasone
1314242844Sjasone	malloc_mutex_lock(&ctl_mtx);
1315286866Sjasone	newind = oldind = oldarena->ind;
1316234370Sjasone	WRITE(newind, unsigned);
1317234370Sjasone	READ(oldind, unsigned);
1318234370Sjasone	if (newind != oldind) {
1319286866Sjasone		arena_t *newarena;
1320234370Sjasone
1321242844Sjasone		if (newind >= ctl_stats.narenas) {
1322234370Sjasone			/* New arena index is out of range. */
1323234370Sjasone			ret = EFAULT;
1324234370Sjasone			goto label_return;
1325234370Sjasone		}
1326234370Sjasone
1327234370Sjasone		/* Initialize arena if necessary. */
1328296221Sjasone		newarena = arena_get(newind, true);
1329286866Sjasone		if (newarena == NULL) {
1330234370Sjasone			ret = EAGAIN;
1331234370Sjasone			goto label_return;
1332234370Sjasone		}
1333286866Sjasone		/* Set new arena/tcache associations. */
1334286866Sjasone		arena_migrate(tsd, oldind, newind);
1335234370Sjasone		if (config_tcache) {
1336286866Sjasone			tcache_t *tcache = tsd_tcache_get(tsd);
1337286866Sjasone			if (tcache != NULL) {
1338286866Sjasone				tcache_arena_reassociate(tcache, oldarena,
1339286866Sjasone				    newarena);
1340234370Sjasone			}
1341234370Sjasone		}
1342234370Sjasone	}
1343234370Sjasone
1344234370Sjasone	ret = 0;
1345234370Sjasonelabel_return:
1346242844Sjasone	malloc_mutex_unlock(&ctl_mtx);
1347234370Sjasone	return (ret);
1348234370Sjasone}
1349234370Sjasone
1350286866SjasoneCTL_TSD_RO_NL_CGEN(config_stats, thread_allocated, tsd_thread_allocated_get,
1351286866Sjasone    uint64_t)
1352286866SjasoneCTL_TSD_RO_NL_CGEN(config_stats, thread_allocatedp, tsd_thread_allocatedp_get,
1353286866Sjasone    uint64_t *)
1354286866SjasoneCTL_TSD_RO_NL_CGEN(config_stats, thread_deallocated, tsd_thread_deallocated_get,
1355286866Sjasone    uint64_t)
1356286866SjasoneCTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp,
1357286866Sjasone    tsd_thread_deallocatedp_get, uint64_t *)
1358234370Sjasone
1359261071Sjasonestatic int
1360261071Sjasonethread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp,
1361261071Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1362261071Sjasone{
1363261071Sjasone	int ret;
1364261071Sjasone	bool oldval;
1365234370Sjasone
1366286866Sjasone	if (!config_tcache)
1367261071Sjasone		return (ENOENT);
1368234370Sjasone
1369261071Sjasone	oldval = tcache_enabled_get();
1370261071Sjasone	if (newp != NULL) {
1371261071Sjasone		if (newlen != sizeof(bool)) {
1372261071Sjasone			ret = EINVAL;
1373261071Sjasone			goto label_return;
1374261071Sjasone		}
1375261071Sjasone		tcache_enabled_set(*(bool *)newp);
1376261071Sjasone	}
1377261071Sjasone	READ(oldval, bool);
1378234370Sjasone
1379261071Sjasone	ret = 0;
1380261071Sjasonelabel_return:
1381261071Sjasone	return (ret);
1382261071Sjasone}
1383234370Sjasone
1384261071Sjasonestatic int
1385261071Sjasonethread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp,
1386261071Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1387261071Sjasone{
1388261071Sjasone	int ret;
1389261071Sjasone
1390286866Sjasone	if (!config_tcache)
1391261071Sjasone		return (ENOENT);
1392261071Sjasone
1393261071Sjasone	READONLY();
1394261071Sjasone	WRITEONLY();
1395261071Sjasone
1396261071Sjasone	tcache_flush();
1397261071Sjasone
1398261071Sjasone	ret = 0;
1399261071Sjasonelabel_return:
1400261071Sjasone	return (ret);
1401261071Sjasone}
1402261071Sjasone
1403286866Sjasonestatic int
1404286866Sjasonethread_prof_name_ctl(const size_t *mib, size_t miblen, void *oldp,
1405286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1406286866Sjasone{
1407286866Sjasone	int ret;
1408286866Sjasone
1409286866Sjasone	if (!config_prof)
1410286866Sjasone		return (ENOENT);
1411286866Sjasone
1412286866Sjasone	READ_XOR_WRITE();
1413286866Sjasone
1414286866Sjasone	if (newp != NULL) {
1415286866Sjasone		tsd_t *tsd;
1416286866Sjasone
1417286866Sjasone		if (newlen != sizeof(const char *)) {
1418286866Sjasone			ret = EINVAL;
1419286866Sjasone			goto label_return;
1420286866Sjasone		}
1421286866Sjasone
1422286866Sjasone		tsd = tsd_fetch();
1423286866Sjasone
1424286866Sjasone		if ((ret = prof_thread_name_set(tsd, *(const char **)newp)) !=
1425286866Sjasone		    0)
1426286866Sjasone			goto label_return;
1427286866Sjasone	} else {
1428286866Sjasone		const char *oldname = prof_thread_name_get();
1429286866Sjasone		READ(oldname, const char *);
1430286866Sjasone	}
1431286866Sjasone
1432286866Sjasone	ret = 0;
1433286866Sjasonelabel_return:
1434286866Sjasone	return (ret);
1435286866Sjasone}
1436286866Sjasone
1437286866Sjasonestatic int
1438286866Sjasonethread_prof_active_ctl(const size_t *mib, size_t miblen, void *oldp,
1439286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1440286866Sjasone{
1441286866Sjasone	int ret;
1442286866Sjasone	bool oldval;
1443286866Sjasone
1444286866Sjasone	if (!config_prof)
1445286866Sjasone		return (ENOENT);
1446286866Sjasone
1447286866Sjasone	oldval = prof_thread_active_get();
1448286866Sjasone	if (newp != NULL) {
1449286866Sjasone		if (newlen != sizeof(bool)) {
1450286866Sjasone			ret = EINVAL;
1451286866Sjasone			goto label_return;
1452286866Sjasone		}
1453286866Sjasone		if (prof_thread_active_set(*(bool *)newp)) {
1454286866Sjasone			ret = EAGAIN;
1455286866Sjasone			goto label_return;
1456286866Sjasone		}
1457286866Sjasone	}
1458286866Sjasone	READ(oldval, bool);
1459286866Sjasone
1460286866Sjasone	ret = 0;
1461286866Sjasonelabel_return:
1462286866Sjasone	return (ret);
1463286866Sjasone}
1464286866Sjasone
1465234370Sjasone/******************************************************************************/
1466234370Sjasone
1467286866Sjasonestatic int
1468286866Sjasonetcache_create_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1469286866Sjasone    void *newp, size_t newlen)
1470286866Sjasone{
1471286866Sjasone	int ret;
1472286866Sjasone	tsd_t *tsd;
1473286866Sjasone	unsigned tcache_ind;
1474286866Sjasone
1475286866Sjasone	if (!config_tcache)
1476286866Sjasone		return (ENOENT);
1477286866Sjasone
1478286866Sjasone	tsd = tsd_fetch();
1479286866Sjasone
1480286866Sjasone	malloc_mutex_lock(&ctl_mtx);
1481286866Sjasone	READONLY();
1482286866Sjasone	if (tcaches_create(tsd, &tcache_ind)) {
1483286866Sjasone		ret = EFAULT;
1484286866Sjasone		goto label_return;
1485286866Sjasone	}
1486286866Sjasone	READ(tcache_ind, unsigned);
1487286866Sjasone
1488286866Sjasone	ret = 0;
1489286866Sjasonelabel_return:
1490286866Sjasone	malloc_mutex_unlock(&ctl_mtx);
1491286866Sjasone	return (ret);
1492286866Sjasone}
1493286866Sjasone
1494286866Sjasonestatic int
1495286866Sjasonetcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1496286866Sjasone    void *newp, size_t newlen)
1497286866Sjasone{
1498286866Sjasone	int ret;
1499286866Sjasone	tsd_t *tsd;
1500286866Sjasone	unsigned tcache_ind;
1501286866Sjasone
1502286866Sjasone	if (!config_tcache)
1503286866Sjasone		return (ENOENT);
1504286866Sjasone
1505286866Sjasone	tsd = tsd_fetch();
1506286866Sjasone
1507286866Sjasone	WRITEONLY();
1508286866Sjasone	tcache_ind = UINT_MAX;
1509286866Sjasone	WRITE(tcache_ind, unsigned);
1510286866Sjasone	if (tcache_ind == UINT_MAX) {
1511286866Sjasone		ret = EFAULT;
1512286866Sjasone		goto label_return;
1513286866Sjasone	}
1514286866Sjasone	tcaches_flush(tsd, tcache_ind);
1515286866Sjasone
1516286866Sjasone	ret = 0;
1517286866Sjasonelabel_return:
1518286866Sjasone	return (ret);
1519286866Sjasone}
1520286866Sjasone
1521286866Sjasonestatic int
1522286866Sjasonetcache_destroy_ctl(const size_t *mib, size_t miblen, void *oldp,
1523286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1524286866Sjasone{
1525286866Sjasone	int ret;
1526286866Sjasone	tsd_t *tsd;
1527286866Sjasone	unsigned tcache_ind;
1528286866Sjasone
1529286866Sjasone	if (!config_tcache)
1530286866Sjasone		return (ENOENT);
1531286866Sjasone
1532286866Sjasone	tsd = tsd_fetch();
1533286866Sjasone
1534286866Sjasone	WRITEONLY();
1535286866Sjasone	tcache_ind = UINT_MAX;
1536286866Sjasone	WRITE(tcache_ind, unsigned);
1537286866Sjasone	if (tcache_ind == UINT_MAX) {
1538286866Sjasone		ret = EFAULT;
1539286866Sjasone		goto label_return;
1540286866Sjasone	}
1541286866Sjasone	tcaches_destroy(tsd, tcache_ind);
1542286866Sjasone
1543286866Sjasone	ret = 0;
1544286866Sjasonelabel_return:
1545286866Sjasone	return (ret);
1546286866Sjasone}
1547286866Sjasone
1548286866Sjasone/******************************************************************************/
1549286866Sjasone
1550242844Sjasonestatic void
1551296221Sjasonearena_i_purge(unsigned arena_ind, bool all)
1552242844Sjasone{
1553242844Sjasone
1554296221Sjasone	malloc_mutex_lock(&ctl_mtx);
1555296221Sjasone	{
1556296221Sjasone		unsigned narenas = ctl_stats.narenas;
1557242844Sjasone
1558296221Sjasone		if (arena_ind == narenas) {
1559296221Sjasone			unsigned i;
1560296221Sjasone			VARIABLE_ARRAY(arena_t *, tarenas, narenas);
1561296221Sjasone
1562296221Sjasone			for (i = 0; i < narenas; i++)
1563296221Sjasone				tarenas[i] = arena_get(i, false);
1564296221Sjasone
1565296221Sjasone			/*
1566296221Sjasone			 * No further need to hold ctl_mtx, since narenas and
1567296221Sjasone			 * tarenas contain everything needed below.
1568296221Sjasone			 */
1569296221Sjasone			malloc_mutex_unlock(&ctl_mtx);
1570296221Sjasone
1571296221Sjasone			for (i = 0; i < narenas; i++) {
1572296221Sjasone				if (tarenas[i] != NULL)
1573296221Sjasone					arena_purge(tarenas[i], all);
1574296221Sjasone			}
1575296221Sjasone		} else {
1576296221Sjasone			arena_t *tarena;
1577296221Sjasone
1578296221Sjasone			assert(arena_ind < narenas);
1579296221Sjasone
1580296221Sjasone			tarena = arena_get(arena_ind, false);
1581296221Sjasone
1582296221Sjasone			/* No further need to hold ctl_mtx. */
1583296221Sjasone			malloc_mutex_unlock(&ctl_mtx);
1584296221Sjasone
1585296221Sjasone			if (tarena != NULL)
1586296221Sjasone				arena_purge(tarena, all);
1587242844Sjasone		}
1588242844Sjasone	}
1589242844Sjasone}
1590242844Sjasone
1591242844Sjasonestatic int
1592242844Sjasonearena_i_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1593242844Sjasone    void *newp, size_t newlen)
1594242844Sjasone{
1595242844Sjasone	int ret;
1596242844Sjasone
1597242844Sjasone	READONLY();
1598242844Sjasone	WRITEONLY();
1599296221Sjasone	arena_i_purge((unsigned)mib[1], true);
1600242844Sjasone
1601242844Sjasone	ret = 0;
1602242844Sjasonelabel_return:
1603242844Sjasone	return (ret);
1604242844Sjasone}
1605242844Sjasone
1606242844Sjasonestatic int
1607296221Sjasonearena_i_decay_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1608296221Sjasone    void *newp, size_t newlen)
1609296221Sjasone{
1610296221Sjasone	int ret;
1611296221Sjasone
1612296221Sjasone	READONLY();
1613296221Sjasone	WRITEONLY();
1614296221Sjasone	arena_i_purge((unsigned)mib[1], false);
1615296221Sjasone
1616296221Sjasone	ret = 0;
1617296221Sjasonelabel_return:
1618296221Sjasone	return (ret);
1619296221Sjasone}
1620296221Sjasone
1621296221Sjasonestatic int
1622242844Sjasonearena_i_dss_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1623242844Sjasone    void *newp, size_t newlen)
1624242844Sjasone{
1625286866Sjasone	int ret;
1626286866Sjasone	const char *dss = NULL;
1627296221Sjasone	unsigned arena_ind = (unsigned)mib[1];
1628242844Sjasone	dss_prec_t dss_prec_old = dss_prec_limit;
1629242844Sjasone	dss_prec_t dss_prec = dss_prec_limit;
1630242844Sjasone
1631242844Sjasone	malloc_mutex_lock(&ctl_mtx);
1632242844Sjasone	WRITE(dss, const char *);
1633286866Sjasone	if (dss != NULL) {
1634286866Sjasone		int i;
1635286866Sjasone		bool match = false;
1636286866Sjasone
1637286866Sjasone		for (i = 0; i < dss_prec_limit; i++) {
1638286866Sjasone			if (strcmp(dss_prec_names[i], dss) == 0) {
1639286866Sjasone				dss_prec = i;
1640286866Sjasone				match = true;
1641286866Sjasone				break;
1642286866Sjasone			}
1643242844Sjasone		}
1644286866Sjasone
1645286866Sjasone		if (!match) {
1646286866Sjasone			ret = EINVAL;
1647286866Sjasone			goto label_return;
1648286866Sjasone		}
1649242844Sjasone	}
1650242844Sjasone
1651242844Sjasone	if (arena_ind < ctl_stats.narenas) {
1652296221Sjasone		arena_t *arena = arena_get(arena_ind, false);
1653286866Sjasone		if (arena == NULL || (dss_prec != dss_prec_limit &&
1654286866Sjasone		    arena_dss_prec_set(arena, dss_prec))) {
1655286866Sjasone			ret = EFAULT;
1656286866Sjasone			goto label_return;
1657286866Sjasone		}
1658286866Sjasone		dss_prec_old = arena_dss_prec_get(arena);
1659242844Sjasone	} else {
1660286866Sjasone		if (dss_prec != dss_prec_limit &&
1661286866Sjasone		    chunk_dss_prec_set(dss_prec)) {
1662286866Sjasone			ret = EFAULT;
1663286866Sjasone			goto label_return;
1664286866Sjasone		}
1665242844Sjasone		dss_prec_old = chunk_dss_prec_get();
1666242844Sjasone	}
1667286866Sjasone
1668242844Sjasone	dss = dss_prec_names[dss_prec_old];
1669242844Sjasone	READ(dss, const char *);
1670286866Sjasone
1671286866Sjasone	ret = 0;
1672286866Sjasonelabel_return:
1673286866Sjasone	malloc_mutex_unlock(&ctl_mtx);
1674286866Sjasone	return (ret);
1675286866Sjasone}
1676286866Sjasone
1677286866Sjasonestatic int
1678286866Sjasonearena_i_lg_dirty_mult_ctl(const size_t *mib, size_t miblen, void *oldp,
1679286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1680286866Sjasone{
1681286866Sjasone	int ret;
1682296221Sjasone	unsigned arena_ind = (unsigned)mib[1];
1683286866Sjasone	arena_t *arena;
1684286866Sjasone
1685296221Sjasone	arena = arena_get(arena_ind, false);
1686286866Sjasone	if (arena == NULL) {
1687242844Sjasone		ret = EFAULT;
1688242844Sjasone		goto label_return;
1689242844Sjasone	}
1690242844Sjasone
1691286866Sjasone	if (oldp != NULL && oldlenp != NULL) {
1692286866Sjasone		size_t oldval = arena_lg_dirty_mult_get(arena);
1693286866Sjasone		READ(oldval, ssize_t);
1694286866Sjasone	}
1695286866Sjasone	if (newp != NULL) {
1696286866Sjasone		if (newlen != sizeof(ssize_t)) {
1697286866Sjasone			ret = EINVAL;
1698286866Sjasone			goto label_return;
1699286866Sjasone		}
1700286866Sjasone		if (arena_lg_dirty_mult_set(arena, *(ssize_t *)newp)) {
1701286866Sjasone			ret = EFAULT;
1702286866Sjasone			goto label_return;
1703286866Sjasone		}
1704286866Sjasone	}
1705286866Sjasone
1706242844Sjasone	ret = 0;
1707242844Sjasonelabel_return:
1708286866Sjasone	return (ret);
1709286866Sjasone}
1710286866Sjasone
1711286866Sjasonestatic int
1712296221Sjasonearena_i_decay_time_ctl(const size_t *mib, size_t miblen, void *oldp,
1713296221Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1714296221Sjasone{
1715296221Sjasone	int ret;
1716296221Sjasone	unsigned arena_ind = (unsigned)mib[1];
1717296221Sjasone	arena_t *arena;
1718296221Sjasone
1719296221Sjasone	arena = arena_get(arena_ind, false);
1720296221Sjasone	if (arena == NULL) {
1721296221Sjasone		ret = EFAULT;
1722296221Sjasone		goto label_return;
1723296221Sjasone	}
1724296221Sjasone
1725296221Sjasone	if (oldp != NULL && oldlenp != NULL) {
1726296221Sjasone		size_t oldval = arena_decay_time_get(arena);
1727296221Sjasone		READ(oldval, ssize_t);
1728296221Sjasone	}
1729296221Sjasone	if (newp != NULL) {
1730296221Sjasone		if (newlen != sizeof(ssize_t)) {
1731296221Sjasone			ret = EINVAL;
1732296221Sjasone			goto label_return;
1733296221Sjasone		}
1734296221Sjasone		if (arena_decay_time_set(arena, *(ssize_t *)newp)) {
1735296221Sjasone			ret = EFAULT;
1736296221Sjasone			goto label_return;
1737296221Sjasone		}
1738296221Sjasone	}
1739296221Sjasone
1740296221Sjasone	ret = 0;
1741296221Sjasonelabel_return:
1742296221Sjasone	return (ret);
1743296221Sjasone}
1744296221Sjasone
1745296221Sjasonestatic int
1746286866Sjasonearena_i_chunk_hooks_ctl(const size_t *mib, size_t miblen, void *oldp,
1747286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1748286866Sjasone{
1749286866Sjasone	int ret;
1750296221Sjasone	unsigned arena_ind = (unsigned)mib[1];
1751286866Sjasone	arena_t *arena;
1752286866Sjasone
1753286866Sjasone	malloc_mutex_lock(&ctl_mtx);
1754286866Sjasone	if (arena_ind < narenas_total_get() && (arena =
1755296221Sjasone	    arena_get(arena_ind, false)) != NULL) {
1756286866Sjasone		if (newp != NULL) {
1757286866Sjasone			chunk_hooks_t old_chunk_hooks, new_chunk_hooks;
1758286866Sjasone			WRITE(new_chunk_hooks, chunk_hooks_t);
1759286866Sjasone			old_chunk_hooks = chunk_hooks_set(arena,
1760286866Sjasone			    &new_chunk_hooks);
1761286866Sjasone			READ(old_chunk_hooks, chunk_hooks_t);
1762286866Sjasone		} else {
1763286866Sjasone			chunk_hooks_t old_chunk_hooks = chunk_hooks_get(arena);
1764286866Sjasone			READ(old_chunk_hooks, chunk_hooks_t);
1765286866Sjasone		}
1766286866Sjasone	} else {
1767286866Sjasone		ret = EFAULT;
1768286866Sjasone		goto label_return;
1769286866Sjasone	}
1770286866Sjasone	ret = 0;
1771286866Sjasonelabel_return:
1772242844Sjasone	malloc_mutex_unlock(&ctl_mtx);
1773242844Sjasone	return (ret);
1774242844Sjasone}
1775242844Sjasone
1776242844Sjasonestatic const ctl_named_node_t *
1777242844Sjasonearena_i_index(const size_t *mib, size_t miblen, size_t i)
1778242844Sjasone{
1779242844Sjasone	const ctl_named_node_t * ret;
1780242844Sjasone
1781242844Sjasone	malloc_mutex_lock(&ctl_mtx);
1782242844Sjasone	if (i > ctl_stats.narenas) {
1783242844Sjasone		ret = NULL;
1784242844Sjasone		goto label_return;
1785242844Sjasone	}
1786242844Sjasone
1787242844Sjasone	ret = super_arena_i_node;
1788242844Sjasonelabel_return:
1789242844Sjasone	malloc_mutex_unlock(&ctl_mtx);
1790242844Sjasone	return (ret);
1791242844Sjasone}
1792242844Sjasone
1793242844Sjasone/******************************************************************************/
1794242844Sjasone
1795242844Sjasonestatic int
1796242844Sjasonearenas_narenas_ctl(const size_t *mib, size_t miblen, void *oldp,
1797242844Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1798242844Sjasone{
1799242844Sjasone	int ret;
1800242844Sjasone	unsigned narenas;
1801234370Sjasone
1802242844Sjasone	malloc_mutex_lock(&ctl_mtx);
1803242844Sjasone	READONLY();
1804242844Sjasone	if (*oldlenp != sizeof(unsigned)) {
1805242844Sjasone		ret = EINVAL;
1806242844Sjasone		goto label_return;
1807242844Sjasone	}
1808242844Sjasone	narenas = ctl_stats.narenas;
1809242844Sjasone	READ(narenas, unsigned);
1810242844Sjasone
1811242844Sjasone	ret = 0;
1812242844Sjasonelabel_return:
1813242844Sjasone	malloc_mutex_unlock(&ctl_mtx);
1814242844Sjasone	return (ret);
1815242844Sjasone}
1816242844Sjasone
1817234370Sjasonestatic int
1818234370Sjasonearenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,
1819234370Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1820234370Sjasone{
1821234370Sjasone	int ret;
1822234370Sjasone	unsigned nread, i;
1823234370Sjasone
1824234370Sjasone	malloc_mutex_lock(&ctl_mtx);
1825234370Sjasone	READONLY();
1826242844Sjasone	if (*oldlenp != ctl_stats.narenas * sizeof(bool)) {
1827234370Sjasone		ret = EINVAL;
1828242844Sjasone		nread = (*oldlenp < ctl_stats.narenas * sizeof(bool))
1829296221Sjasone		    ? (unsigned)(*oldlenp / sizeof(bool)) : ctl_stats.narenas;
1830234370Sjasone	} else {
1831234370Sjasone		ret = 0;
1832242844Sjasone		nread = ctl_stats.narenas;
1833234370Sjasone	}
1834234370Sjasone
1835234370Sjasone	for (i = 0; i < nread; i++)
1836234370Sjasone		((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
1837234370Sjasone
1838234370Sjasonelabel_return:
1839234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
1840234370Sjasone	return (ret);
1841234370Sjasone}
1842234370Sjasone
1843286866Sjasonestatic int
1844286866Sjasonearenas_lg_dirty_mult_ctl(const size_t *mib, size_t miblen, void *oldp,
1845286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1846286866Sjasone{
1847286866Sjasone	int ret;
1848286866Sjasone
1849286866Sjasone	if (oldp != NULL && oldlenp != NULL) {
1850286866Sjasone		size_t oldval = arena_lg_dirty_mult_default_get();
1851286866Sjasone		READ(oldval, ssize_t);
1852286866Sjasone	}
1853286866Sjasone	if (newp != NULL) {
1854286866Sjasone		if (newlen != sizeof(ssize_t)) {
1855286866Sjasone			ret = EINVAL;
1856286866Sjasone			goto label_return;
1857286866Sjasone		}
1858286866Sjasone		if (arena_lg_dirty_mult_default_set(*(ssize_t *)newp)) {
1859286866Sjasone			ret = EFAULT;
1860286866Sjasone			goto label_return;
1861286866Sjasone		}
1862286866Sjasone	}
1863286866Sjasone
1864286866Sjasone	ret = 0;
1865286866Sjasonelabel_return:
1866286866Sjasone	return (ret);
1867286866Sjasone}
1868286866Sjasone
1869296221Sjasonestatic int
1870296221Sjasonearenas_decay_time_ctl(const size_t *mib, size_t miblen, void *oldp,
1871296221Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1872296221Sjasone{
1873296221Sjasone	int ret;
1874296221Sjasone
1875296221Sjasone	if (oldp != NULL && oldlenp != NULL) {
1876296221Sjasone		size_t oldval = arena_decay_time_default_get();
1877296221Sjasone		READ(oldval, ssize_t);
1878296221Sjasone	}
1879296221Sjasone	if (newp != NULL) {
1880296221Sjasone		if (newlen != sizeof(ssize_t)) {
1881296221Sjasone			ret = EINVAL;
1882296221Sjasone			goto label_return;
1883296221Sjasone		}
1884296221Sjasone		if (arena_decay_time_default_set(*(ssize_t *)newp)) {
1885296221Sjasone			ret = EFAULT;
1886296221Sjasone			goto label_return;
1887296221Sjasone		}
1888296221Sjasone	}
1889296221Sjasone
1890296221Sjasone	ret = 0;
1891296221Sjasonelabel_return:
1892296221Sjasone	return (ret);
1893296221Sjasone}
1894296221Sjasone
1895234370SjasoneCTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
1896234370SjasoneCTL_RO_NL_GEN(arenas_page, PAGE, size_t)
1897234370SjasoneCTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)
1898234370SjasoneCTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)
1899234370SjasoneCTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)
1900261071SjasoneCTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)
1901261071SjasoneCTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)
1902261071SjasoneCTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)
1903261071Sjasonestatic const ctl_named_node_t *
1904261071Sjasonearenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)
1905261071Sjasone{
1906261071Sjasone
1907261071Sjasone	if (i > NBINS)
1908261071Sjasone		return (NULL);
1909261071Sjasone	return (super_arenas_bin_i_node);
1910261071Sjasone}
1911261071Sjasone
1912286866SjasoneCTL_RO_NL_GEN(arenas_nlruns, nlclasses, unsigned)
1913296221SjasoneCTL_RO_NL_GEN(arenas_lrun_i_size, index2size(NBINS+(szind_t)mib[2]), size_t)
1914261071Sjasonestatic const ctl_named_node_t *
1915261071Sjasonearenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)
1916261071Sjasone{
1917234370Sjasone
1918261071Sjasone	if (i > nlclasses)
1919261071Sjasone		return (NULL);
1920261071Sjasone	return (super_arenas_lrun_i_node);
1921261071Sjasone}
1922261071Sjasone
1923286866SjasoneCTL_RO_NL_GEN(arenas_nhchunks, nhclasses, unsigned)
1924296221SjasoneCTL_RO_NL_GEN(arenas_hchunk_i_size, index2size(NBINS+nlclasses+(szind_t)mib[2]),
1925296221Sjasone    size_t)
1926286866Sjasonestatic const ctl_named_node_t *
1927286866Sjasonearenas_hchunk_i_index(const size_t *mib, size_t miblen, size_t i)
1928234370Sjasone{
1929234370Sjasone
1930286866Sjasone	if (i > nhclasses)
1931286866Sjasone		return (NULL);
1932286866Sjasone	return (super_arenas_hchunk_i_node);
1933242844Sjasone}
1934234370Sjasone
1935242844Sjasonestatic int
1936242844Sjasonearenas_extend_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1937242844Sjasone    void *newp, size_t newlen)
1938242844Sjasone{
1939242844Sjasone	int ret;
1940245868Sjasone	unsigned narenas;
1941242844Sjasone
1942242844Sjasone	malloc_mutex_lock(&ctl_mtx);
1943242844Sjasone	READONLY();
1944242844Sjasone	if (ctl_grow()) {
1945242844Sjasone		ret = EAGAIN;
1946242844Sjasone		goto label_return;
1947234370Sjasone	}
1948245868Sjasone	narenas = ctl_stats.narenas - 1;
1949245868Sjasone	READ(narenas, unsigned);
1950234370Sjasone
1951234370Sjasone	ret = 0;
1952234370Sjasonelabel_return:
1953242844Sjasone	malloc_mutex_unlock(&ctl_mtx);
1954234370Sjasone	return (ret);
1955234370Sjasone}
1956234370Sjasone
1957234370Sjasone/******************************************************************************/
1958234370Sjasone
1959234370Sjasonestatic int
1960286866Sjasoneprof_thread_active_init_ctl(const size_t *mib, size_t miblen, void *oldp,
1961286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1962286866Sjasone{
1963286866Sjasone	int ret;
1964286866Sjasone	bool oldval;
1965286866Sjasone
1966286866Sjasone	if (!config_prof)
1967286866Sjasone		return (ENOENT);
1968286866Sjasone
1969286866Sjasone	if (newp != NULL) {
1970286866Sjasone		if (newlen != sizeof(bool)) {
1971286866Sjasone			ret = EINVAL;
1972286866Sjasone			goto label_return;
1973286866Sjasone		}
1974286866Sjasone		oldval = prof_thread_active_init_set(*(bool *)newp);
1975286866Sjasone	} else
1976286866Sjasone		oldval = prof_thread_active_init_get();
1977286866Sjasone	READ(oldval, bool);
1978286866Sjasone
1979286866Sjasone	ret = 0;
1980286866Sjasonelabel_return:
1981286866Sjasone	return (ret);
1982286866Sjasone}
1983286866Sjasone
1984286866Sjasonestatic int
1985234370Sjasoneprof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1986234370Sjasone    void *newp, size_t newlen)
1987234370Sjasone{
1988234370Sjasone	int ret;
1989234370Sjasone	bool oldval;
1990234370Sjasone
1991286866Sjasone	if (!config_prof)
1992234370Sjasone		return (ENOENT);
1993234370Sjasone
1994234370Sjasone	if (newp != NULL) {
1995286866Sjasone		if (newlen != sizeof(bool)) {
1996286866Sjasone			ret = EINVAL;
1997286866Sjasone			goto label_return;
1998286866Sjasone		}
1999286866Sjasone		oldval = prof_active_set(*(bool *)newp);
2000286866Sjasone	} else
2001286866Sjasone		oldval = prof_active_get();
2002234370Sjasone	READ(oldval, bool);
2003234370Sjasone
2004234370Sjasone	ret = 0;
2005234370Sjasonelabel_return:
2006234370Sjasone	return (ret);
2007234370Sjasone}
2008234370Sjasone
2009234370Sjasonestatic int
2010234370Sjasoneprof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
2011234370Sjasone    void *newp, size_t newlen)
2012234370Sjasone{
2013234370Sjasone	int ret;
2014234370Sjasone	const char *filename = NULL;
2015234370Sjasone
2016286866Sjasone	if (!config_prof)
2017234370Sjasone		return (ENOENT);
2018234370Sjasone
2019234370Sjasone	WRITEONLY();
2020234370Sjasone	WRITE(filename, const char *);
2021234370Sjasone
2022234370Sjasone	if (prof_mdump(filename)) {
2023234370Sjasone		ret = EFAULT;
2024234370Sjasone		goto label_return;
2025234370Sjasone	}
2026234370Sjasone
2027234370Sjasone	ret = 0;
2028234370Sjasonelabel_return:
2029234370Sjasone	return (ret);
2030234370Sjasone}
2031234370Sjasone
2032286866Sjasonestatic int
2033286866Sjasoneprof_gdump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
2034286866Sjasone    void *newp, size_t newlen)
2035286866Sjasone{
2036286866Sjasone	int ret;
2037286866Sjasone	bool oldval;
2038286866Sjasone
2039286866Sjasone	if (!config_prof)
2040286866Sjasone		return (ENOENT);
2041286866Sjasone
2042286866Sjasone	if (newp != NULL) {
2043286866Sjasone		if (newlen != sizeof(bool)) {
2044286866Sjasone			ret = EINVAL;
2045286866Sjasone			goto label_return;
2046286866Sjasone		}
2047286866Sjasone		oldval = prof_gdump_set(*(bool *)newp);
2048286866Sjasone	} else
2049286866Sjasone		oldval = prof_gdump_get();
2050286866Sjasone	READ(oldval, bool);
2051286866Sjasone
2052286866Sjasone	ret = 0;
2053286866Sjasonelabel_return:
2054286866Sjasone	return (ret);
2055286866Sjasone}
2056286866Sjasone
2057286866Sjasonestatic int
2058286866Sjasoneprof_reset_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
2059286866Sjasone    void *newp, size_t newlen)
2060286866Sjasone{
2061286866Sjasone	int ret;
2062286866Sjasone	size_t lg_sample = lg_prof_sample;
2063286866Sjasone	tsd_t *tsd;
2064286866Sjasone
2065286866Sjasone	if (!config_prof)
2066286866Sjasone		return (ENOENT);
2067286866Sjasone
2068286866Sjasone	WRITEONLY();
2069286866Sjasone	WRITE(lg_sample, size_t);
2070286866Sjasone	if (lg_sample >= (sizeof(uint64_t) << 3))
2071286866Sjasone		lg_sample = (sizeof(uint64_t) << 3) - 1;
2072286866Sjasone
2073286866Sjasone	tsd = tsd_fetch();
2074286866Sjasone
2075286866Sjasone	prof_reset(tsd, lg_sample);
2076286866Sjasone
2077286866Sjasone	ret = 0;
2078286866Sjasonelabel_return:
2079286866Sjasone	return (ret);
2080286866Sjasone}
2081286866Sjasone
2082234370SjasoneCTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
2083286866SjasoneCTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t)
2084234370Sjasone
2085234370Sjasone/******************************************************************************/
2086234370Sjasone
2087261071SjasoneCTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)
2088261071SjasoneCTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)
2089261071SjasoneCTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
2090286866SjasoneCTL_RO_CGEN(config_stats, stats_metadata, ctl_stats.metadata, size_t)
2091286866SjasoneCTL_RO_CGEN(config_stats, stats_resident, ctl_stats.resident, size_t)
2092261071SjasoneCTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)
2093261071Sjasone
2094261071SjasoneCTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)
2095286866SjasoneCTL_RO_GEN(stats_arenas_i_lg_dirty_mult, ctl_stats.arenas[mib[2]].lg_dirty_mult,
2096286866Sjasone    ssize_t)
2097296221SjasoneCTL_RO_GEN(stats_arenas_i_decay_time, ctl_stats.arenas[mib[2]].decay_time,
2098296221Sjasone    ssize_t)
2099261071SjasoneCTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)
2100261071SjasoneCTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
2101261071SjasoneCTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
2102261071SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
2103261071Sjasone    ctl_stats.arenas[mib[2]].astats.mapped, size_t)
2104261071SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
2105261071Sjasone    ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
2106261071SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
2107261071Sjasone    ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)
2108261071SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_purged,
2109261071Sjasone    ctl_stats.arenas[mib[2]].astats.purged, uint64_t)
2110286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_metadata_mapped,
2111286866Sjasone    ctl_stats.arenas[mib[2]].astats.metadata_mapped, size_t)
2112286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_metadata_allocated,
2113286866Sjasone    ctl_stats.arenas[mib[2]].astats.metadata_allocated, size_t)
2114261071Sjasone
2115234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
2116234370Sjasone    ctl_stats.arenas[mib[2]].allocated_small, size_t)
2117234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
2118234370Sjasone    ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)
2119234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
2120234370Sjasone    ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)
2121234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
2122234370Sjasone    ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)
2123234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
2124234370Sjasone    ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)
2125234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
2126234370Sjasone    ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)
2127234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
2128234370Sjasone    ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)
2129234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
2130234370Sjasone    ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)
2131286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_huge_allocated,
2132286866Sjasone    ctl_stats.arenas[mib[2]].astats.allocated_huge, size_t)
2133286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_huge_nmalloc,
2134286866Sjasone    ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t)
2135286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_huge_ndalloc,
2136286866Sjasone    ctl_stats.arenas[mib[2]].astats.ndalloc_huge, uint64_t)
2137286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_huge_nrequests,
2138286866Sjasone    ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t) /* Intentional. */
2139234370Sjasone
2140234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
2141234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)
2142234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
2143234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)
2144234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
2145234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)
2146286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curregs,
2147286866Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].curregs, size_t)
2148234370SjasoneCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,
2149234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)
2150234370SjasoneCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,
2151234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)
2152234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,
2153234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)
2154234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,
2155234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)
2156234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,
2157234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)
2158234370Sjasone
2159242844Sjasonestatic const ctl_named_node_t *
2160234370Sjasonestats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j)
2161234370Sjasone{
2162234370Sjasone
2163234370Sjasone	if (j > NBINS)
2164234370Sjasone		return (NULL);
2165234370Sjasone	return (super_stats_arenas_i_bins_j_node);
2166234370Sjasone}
2167234370Sjasone
2168234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,
2169234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)
2170234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,
2171234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)
2172234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,
2173234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)
2174234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,
2175234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)
2176234370Sjasone
2177242844Sjasonestatic const ctl_named_node_t *
2178234370Sjasonestats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j)
2179234370Sjasone{
2180234370Sjasone
2181234370Sjasone	if (j > nlclasses)
2182234370Sjasone		return (NULL);
2183234370Sjasone	return (super_stats_arenas_i_lruns_j_node);
2184234370Sjasone}
2185234370Sjasone
2186286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nmalloc,
2187286866Sjasone    ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, uint64_t)
2188286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_ndalloc,
2189286866Sjasone    ctl_stats.arenas[mib[2]].hstats[mib[4]].ndalloc, uint64_t)
2190286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nrequests,
2191286866Sjasone    ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, /* Intentional. */
2192286866Sjasone    uint64_t)
2193286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_curhchunks,
2194286866Sjasone    ctl_stats.arenas[mib[2]].hstats[mib[4]].curhchunks, size_t)
2195286866Sjasone
2196242844Sjasonestatic const ctl_named_node_t *
2197286866Sjasonestats_arenas_i_hchunks_j_index(const size_t *mib, size_t miblen, size_t j)
2198286866Sjasone{
2199286866Sjasone
2200286866Sjasone	if (j > nhclasses)
2201286866Sjasone		return (NULL);
2202286866Sjasone	return (super_stats_arenas_i_hchunks_j_node);
2203286866Sjasone}
2204286866Sjasone
2205286866Sjasonestatic const ctl_named_node_t *
2206234370Sjasonestats_arenas_i_index(const size_t *mib, size_t miblen, size_t i)
2207234370Sjasone{
2208235238Sjasone	const ctl_named_node_t * ret;
2209234370Sjasone
2210234370Sjasone	malloc_mutex_lock(&ctl_mtx);
2211286866Sjasone	if (i > ctl_stats.narenas || !ctl_stats.arenas[i].initialized) {
2212234370Sjasone		ret = NULL;
2213234370Sjasone		goto label_return;
2214234370Sjasone	}
2215234370Sjasone
2216234370Sjasone	ret = super_stats_arenas_i_node;
2217234370Sjasonelabel_return:
2218234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
2219234370Sjasone	return (ret);
2220234370Sjasone}
2221