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)							\
45299587Sjasonestatic int	n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,	\
46299587Sjasone    void *oldp, size_t *oldlenp, void *newp, size_t newlen);
47234370Sjasone
48234370Sjasone#define	INDEX_PROTO(n)							\
49299587Sjasonestatic const ctl_named_node_t	*n##_index(tsdn_t *tsdn,		\
50299587Sjasone    const size_t *mib, 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);
54299587Sjasonestatic void	ctl_arena_stats_amerge(tsdn_t *tsdn, 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);
58299587Sjasonestatic void	ctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, unsigned i);
59299587Sjasonestatic bool	ctl_grow(tsdn_t *tsdn);
60299587Sjasonestatic void	ctl_refresh(tsdn_t *tsdn);
61299587Sjasonestatic bool	ctl_init(tsdn_t *tsdn);
62299587Sjasonestatic int	ctl_lookup(tsdn_t *tsdn, const char *name,
63299587Sjasone    ctl_node_t const **nodesp, 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)
120299587Sjasonestatic void	arena_i_purge(tsdn_t *tsdn, unsigned arena_ind, bool all);
121242844SjasoneCTL_PROTO(arena_i_purge)
122296221SjasoneCTL_PROTO(arena_i_decay)
123299587SjasoneCTL_PROTO(arena_i_reset)
124242844SjasoneCTL_PROTO(arena_i_dss)
125286866SjasoneCTL_PROTO(arena_i_lg_dirty_mult)
126296221SjasoneCTL_PROTO(arena_i_decay_time)
127286866SjasoneCTL_PROTO(arena_i_chunk_hooks)
128242844SjasoneINDEX_PROTO(arena_i)
129234370SjasoneCTL_PROTO(arenas_bin_i_size)
130234370SjasoneCTL_PROTO(arenas_bin_i_nregs)
131234370SjasoneCTL_PROTO(arenas_bin_i_run_size)
132234370SjasoneINDEX_PROTO(arenas_bin_i)
133234370SjasoneCTL_PROTO(arenas_lrun_i_size)
134234370SjasoneINDEX_PROTO(arenas_lrun_i)
135286866SjasoneCTL_PROTO(arenas_hchunk_i_size)
136286866SjasoneINDEX_PROTO(arenas_hchunk_i)
137234370SjasoneCTL_PROTO(arenas_narenas)
138234370SjasoneCTL_PROTO(arenas_initialized)
139286866SjasoneCTL_PROTO(arenas_lg_dirty_mult)
140296221SjasoneCTL_PROTO(arenas_decay_time)
141234370SjasoneCTL_PROTO(arenas_quantum)
142234370SjasoneCTL_PROTO(arenas_page)
143234370SjasoneCTL_PROTO(arenas_tcache_max)
144234370SjasoneCTL_PROTO(arenas_nbins)
145234370SjasoneCTL_PROTO(arenas_nhbins)
146234370SjasoneCTL_PROTO(arenas_nlruns)
147286866SjasoneCTL_PROTO(arenas_nhchunks)
148242844SjasoneCTL_PROTO(arenas_extend)
149286866SjasoneCTL_PROTO(prof_thread_active_init)
150234370SjasoneCTL_PROTO(prof_active)
151234370SjasoneCTL_PROTO(prof_dump)
152286866SjasoneCTL_PROTO(prof_gdump)
153286866SjasoneCTL_PROTO(prof_reset)
154234370SjasoneCTL_PROTO(prof_interval)
155286866SjasoneCTL_PROTO(lg_prof_sample)
156234370SjasoneCTL_PROTO(stats_arenas_i_small_allocated)
157234370SjasoneCTL_PROTO(stats_arenas_i_small_nmalloc)
158234370SjasoneCTL_PROTO(stats_arenas_i_small_ndalloc)
159234370SjasoneCTL_PROTO(stats_arenas_i_small_nrequests)
160234370SjasoneCTL_PROTO(stats_arenas_i_large_allocated)
161234370SjasoneCTL_PROTO(stats_arenas_i_large_nmalloc)
162234370SjasoneCTL_PROTO(stats_arenas_i_large_ndalloc)
163234370SjasoneCTL_PROTO(stats_arenas_i_large_nrequests)
164286866SjasoneCTL_PROTO(stats_arenas_i_huge_allocated)
165286866SjasoneCTL_PROTO(stats_arenas_i_huge_nmalloc)
166286866SjasoneCTL_PROTO(stats_arenas_i_huge_ndalloc)
167286866SjasoneCTL_PROTO(stats_arenas_i_huge_nrequests)
168234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nmalloc)
169234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_ndalloc)
170234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nrequests)
171286866SjasoneCTL_PROTO(stats_arenas_i_bins_j_curregs)
172234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nfills)
173234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nflushes)
174234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nruns)
175234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nreruns)
176234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_curruns)
177234370SjasoneINDEX_PROTO(stats_arenas_i_bins_j)
178234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_nmalloc)
179234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_ndalloc)
180234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_nrequests)
181234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_curruns)
182234370SjasoneINDEX_PROTO(stats_arenas_i_lruns_j)
183286866SjasoneCTL_PROTO(stats_arenas_i_hchunks_j_nmalloc)
184286866SjasoneCTL_PROTO(stats_arenas_i_hchunks_j_ndalloc)
185286866SjasoneCTL_PROTO(stats_arenas_i_hchunks_j_nrequests)
186286866SjasoneCTL_PROTO(stats_arenas_i_hchunks_j_curhchunks)
187286866SjasoneINDEX_PROTO(stats_arenas_i_hchunks_j)
188234370SjasoneCTL_PROTO(stats_arenas_i_nthreads)
189242844SjasoneCTL_PROTO(stats_arenas_i_dss)
190286866SjasoneCTL_PROTO(stats_arenas_i_lg_dirty_mult)
191296221SjasoneCTL_PROTO(stats_arenas_i_decay_time)
192234370SjasoneCTL_PROTO(stats_arenas_i_pactive)
193234370SjasoneCTL_PROTO(stats_arenas_i_pdirty)
194234370SjasoneCTL_PROTO(stats_arenas_i_mapped)
195299587SjasoneCTL_PROTO(stats_arenas_i_retained)
196234370SjasoneCTL_PROTO(stats_arenas_i_npurge)
197234370SjasoneCTL_PROTO(stats_arenas_i_nmadvise)
198234370SjasoneCTL_PROTO(stats_arenas_i_purged)
199286866SjasoneCTL_PROTO(stats_arenas_i_metadata_mapped)
200286866SjasoneCTL_PROTO(stats_arenas_i_metadata_allocated)
201234370SjasoneINDEX_PROTO(stats_arenas_i)
202234370SjasoneCTL_PROTO(stats_cactive)
203234370SjasoneCTL_PROTO(stats_allocated)
204234370SjasoneCTL_PROTO(stats_active)
205286866SjasoneCTL_PROTO(stats_metadata)
206286866SjasoneCTL_PROTO(stats_resident)
207234370SjasoneCTL_PROTO(stats_mapped)
208299587SjasoneCTL_PROTO(stats_retained)
209234370Sjasone
210234370Sjasone/******************************************************************************/
211234370Sjasone/* mallctl tree. */
212234370Sjasone
213234370Sjasone/* Maximum tree depth. */
214234370Sjasone#define	CTL_MAX_DEPTH	6
215234370Sjasone
216235238Sjasone#define	NAME(n)	{true},	n
217235238Sjasone#define	CHILD(t, c)							\
218235238Sjasone	sizeof(c##_node) / sizeof(ctl_##t##_node_t),			\
219235238Sjasone	(ctl_node_t *)c##_node,						\
220235238Sjasone	NULL
221235238Sjasone#define	CTL(c)	0, NULL, c##_ctl
222234370Sjasone
223234370Sjasone/*
224234370Sjasone * Only handles internal indexed nodes, since there are currently no external
225234370Sjasone * ones.
226234370Sjasone */
227235238Sjasone#define	INDEX(i)	{false},	i##_index
228234370Sjasone
229286866Sjasonestatic const ctl_named_node_t	thread_tcache_node[] = {
230234370Sjasone	{NAME("enabled"),	CTL(thread_tcache_enabled)},
231234370Sjasone	{NAME("flush"),		CTL(thread_tcache_flush)}
232234370Sjasone};
233234370Sjasone
234286866Sjasonestatic const ctl_named_node_t	thread_prof_node[] = {
235286866Sjasone	{NAME("name"),		CTL(thread_prof_name)},
236286866Sjasone	{NAME("active"),	CTL(thread_prof_active)}
237286866Sjasone};
238286866Sjasone
239235238Sjasonestatic const ctl_named_node_t	thread_node[] = {
240234370Sjasone	{NAME("arena"),		CTL(thread_arena)},
241234370Sjasone	{NAME("allocated"),	CTL(thread_allocated)},
242234370Sjasone	{NAME("allocatedp"),	CTL(thread_allocatedp)},
243234370Sjasone	{NAME("deallocated"),	CTL(thread_deallocated)},
244234370Sjasone	{NAME("deallocatedp"),	CTL(thread_deallocatedp)},
245286866Sjasone	{NAME("tcache"),	CHILD(named, thread_tcache)},
246286866Sjasone	{NAME("prof"),		CHILD(named, thread_prof)}
247234370Sjasone};
248234370Sjasone
249235238Sjasonestatic const ctl_named_node_t	config_node[] = {
250286866Sjasone	{NAME("cache_oblivious"), CTL(config_cache_oblivious)},
251286866Sjasone	{NAME("debug"),		CTL(config_debug)},
252286866Sjasone	{NAME("fill"),		CTL(config_fill)},
253286866Sjasone	{NAME("lazy_lock"),	CTL(config_lazy_lock)},
254296221Sjasone	{NAME("malloc_conf"),	CTL(config_malloc_conf)},
255286866Sjasone	{NAME("munmap"),	CTL(config_munmap)},
256286866Sjasone	{NAME("prof"),		CTL(config_prof)},
257286866Sjasone	{NAME("prof_libgcc"),	CTL(config_prof_libgcc)},
258286866Sjasone	{NAME("prof_libunwind"), CTL(config_prof_libunwind)},
259286866Sjasone	{NAME("stats"),		CTL(config_stats)},
260286866Sjasone	{NAME("tcache"),	CTL(config_tcache)},
261286866Sjasone	{NAME("tls"),		CTL(config_tls)},
262286866Sjasone	{NAME("utrace"),	CTL(config_utrace)},
263286866Sjasone	{NAME("valgrind"),	CTL(config_valgrind)},
264286866Sjasone	{NAME("xmalloc"),	CTL(config_xmalloc)}
265234370Sjasone};
266234370Sjasone
267235238Sjasonestatic const ctl_named_node_t opt_node[] = {
268286866Sjasone	{NAME("abort"),		CTL(opt_abort)},
269286866Sjasone	{NAME("dss"),		CTL(opt_dss)},
270286866Sjasone	{NAME("lg_chunk"),	CTL(opt_lg_chunk)},
271286866Sjasone	{NAME("narenas"),	CTL(opt_narenas)},
272296221Sjasone	{NAME("purge"),		CTL(opt_purge)},
273286866Sjasone	{NAME("lg_dirty_mult"),	CTL(opt_lg_dirty_mult)},
274296221Sjasone	{NAME("decay_time"),	CTL(opt_decay_time)},
275286866Sjasone	{NAME("stats_print"),	CTL(opt_stats_print)},
276286866Sjasone	{NAME("junk"),		CTL(opt_junk)},
277286866Sjasone	{NAME("zero"),		CTL(opt_zero)},
278286866Sjasone	{NAME("quarantine"),	CTL(opt_quarantine)},
279286866Sjasone	{NAME("redzone"),	CTL(opt_redzone)},
280286866Sjasone	{NAME("utrace"),	CTL(opt_utrace)},
281286866Sjasone	{NAME("xmalloc"),	CTL(opt_xmalloc)},
282286866Sjasone	{NAME("tcache"),	CTL(opt_tcache)},
283286866Sjasone	{NAME("lg_tcache_max"),	CTL(opt_lg_tcache_max)},
284286866Sjasone	{NAME("prof"),		CTL(opt_prof)},
285286866Sjasone	{NAME("prof_prefix"),	CTL(opt_prof_prefix)},
286286866Sjasone	{NAME("prof_active"),	CTL(opt_prof_active)},
287286866Sjasone	{NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)},
288286866Sjasone	{NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
289286866Sjasone	{NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
290286866Sjasone	{NAME("prof_gdump"),	CTL(opt_prof_gdump)},
291286866Sjasone	{NAME("prof_final"),	CTL(opt_prof_final)},
292286866Sjasone	{NAME("prof_leak"),	CTL(opt_prof_leak)},
293286866Sjasone	{NAME("prof_accum"),	CTL(opt_prof_accum)}
294234370Sjasone};
295234370Sjasone
296286866Sjasonestatic const ctl_named_node_t	tcache_node[] = {
297286866Sjasone	{NAME("create"),	CTL(tcache_create)},
298286866Sjasone	{NAME("flush"),		CTL(tcache_flush)},
299286866Sjasone	{NAME("destroy"),	CTL(tcache_destroy)}
300286866Sjasone};
301286866Sjasone
302242844Sjasonestatic const ctl_named_node_t arena_i_node[] = {
303286866Sjasone	{NAME("purge"),		CTL(arena_i_purge)},
304296221Sjasone	{NAME("decay"),		CTL(arena_i_decay)},
305299587Sjasone	{NAME("reset"),		CTL(arena_i_reset)},
306286866Sjasone	{NAME("dss"),		CTL(arena_i_dss)},
307286866Sjasone	{NAME("lg_dirty_mult"),	CTL(arena_i_lg_dirty_mult)},
308296221Sjasone	{NAME("decay_time"),	CTL(arena_i_decay_time)},
309286866Sjasone	{NAME("chunk_hooks"),	CTL(arena_i_chunk_hooks)}
310242844Sjasone};
311242844Sjasonestatic const ctl_named_node_t super_arena_i_node[] = {
312286866Sjasone	{NAME(""),		CHILD(named, arena_i)}
313242844Sjasone};
314242844Sjasone
315242844Sjasonestatic const ctl_indexed_node_t arena_node[] = {
316242844Sjasone	{INDEX(arena_i)}
317242844Sjasone};
318242844Sjasone
319235238Sjasonestatic const ctl_named_node_t arenas_bin_i_node[] = {
320286866Sjasone	{NAME("size"),		CTL(arenas_bin_i_size)},
321286866Sjasone	{NAME("nregs"),		CTL(arenas_bin_i_nregs)},
322286866Sjasone	{NAME("run_size"),	CTL(arenas_bin_i_run_size)}
323234370Sjasone};
324235238Sjasonestatic const ctl_named_node_t super_arenas_bin_i_node[] = {
325286866Sjasone	{NAME(""),		CHILD(named, arenas_bin_i)}
326234370Sjasone};
327234370Sjasone
328235238Sjasonestatic const ctl_indexed_node_t arenas_bin_node[] = {
329234370Sjasone	{INDEX(arenas_bin_i)}
330234370Sjasone};
331234370Sjasone
332235238Sjasonestatic const ctl_named_node_t arenas_lrun_i_node[] = {
333286866Sjasone	{NAME("size"),		CTL(arenas_lrun_i_size)}
334234370Sjasone};
335235238Sjasonestatic const ctl_named_node_t super_arenas_lrun_i_node[] = {
336286866Sjasone	{NAME(""),		CHILD(named, arenas_lrun_i)}
337234370Sjasone};
338234370Sjasone
339235238Sjasonestatic const ctl_indexed_node_t arenas_lrun_node[] = {
340234370Sjasone	{INDEX(arenas_lrun_i)}
341234370Sjasone};
342234370Sjasone
343286866Sjasonestatic const ctl_named_node_t arenas_hchunk_i_node[] = {
344286866Sjasone	{NAME("size"),		CTL(arenas_hchunk_i_size)}
345286866Sjasone};
346286866Sjasonestatic const ctl_named_node_t super_arenas_hchunk_i_node[] = {
347286866Sjasone	{NAME(""),		CHILD(named, arenas_hchunk_i)}
348286866Sjasone};
349286866Sjasone
350286866Sjasonestatic const ctl_indexed_node_t arenas_hchunk_node[] = {
351286866Sjasone	{INDEX(arenas_hchunk_i)}
352286866Sjasone};
353286866Sjasone
354235238Sjasonestatic const ctl_named_node_t arenas_node[] = {
355286866Sjasone	{NAME("narenas"),	CTL(arenas_narenas)},
356286866Sjasone	{NAME("initialized"),	CTL(arenas_initialized)},
357286866Sjasone	{NAME("lg_dirty_mult"),	CTL(arenas_lg_dirty_mult)},
358296221Sjasone	{NAME("decay_time"),	CTL(arenas_decay_time)},
359286866Sjasone	{NAME("quantum"),	CTL(arenas_quantum)},
360286866Sjasone	{NAME("page"),		CTL(arenas_page)},
361286866Sjasone	{NAME("tcache_max"),	CTL(arenas_tcache_max)},
362286866Sjasone	{NAME("nbins"),		CTL(arenas_nbins)},
363286866Sjasone	{NAME("nhbins"),	CTL(arenas_nhbins)},
364286866Sjasone	{NAME("bin"),		CHILD(indexed, arenas_bin)},
365286866Sjasone	{NAME("nlruns"),	CTL(arenas_nlruns)},
366286866Sjasone	{NAME("lrun"),		CHILD(indexed, arenas_lrun)},
367286866Sjasone	{NAME("nhchunks"),	CTL(arenas_nhchunks)},
368286866Sjasone	{NAME("hchunk"),	CHILD(indexed, arenas_hchunk)},
369286866Sjasone	{NAME("extend"),	CTL(arenas_extend)}
370234370Sjasone};
371234370Sjasone
372235238Sjasonestatic const ctl_named_node_t	prof_node[] = {
373286866Sjasone	{NAME("thread_active_init"), CTL(prof_thread_active_init)},
374234370Sjasone	{NAME("active"),	CTL(prof_active)},
375234370Sjasone	{NAME("dump"),		CTL(prof_dump)},
376286866Sjasone	{NAME("gdump"),		CTL(prof_gdump)},
377286866Sjasone	{NAME("reset"),		CTL(prof_reset)},
378286866Sjasone	{NAME("interval"),	CTL(prof_interval)},
379286866Sjasone	{NAME("lg_sample"),	CTL(lg_prof_sample)}
380234370Sjasone};
381234370Sjasone
382286866Sjasonestatic const ctl_named_node_t stats_arenas_i_metadata_node[] = {
383286866Sjasone	{NAME("mapped"),	CTL(stats_arenas_i_metadata_mapped)},
384286866Sjasone	{NAME("allocated"),	CTL(stats_arenas_i_metadata_allocated)}
385234370Sjasone};
386234370Sjasone
387235238Sjasonestatic const ctl_named_node_t stats_arenas_i_small_node[] = {
388286866Sjasone	{NAME("allocated"),	CTL(stats_arenas_i_small_allocated)},
389286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_small_nmalloc)},
390286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_small_ndalloc)},
391286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_small_nrequests)}
392234370Sjasone};
393234370Sjasone
394235238Sjasonestatic const ctl_named_node_t stats_arenas_i_large_node[] = {
395286866Sjasone	{NAME("allocated"),	CTL(stats_arenas_i_large_allocated)},
396286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_large_nmalloc)},
397286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_large_ndalloc)},
398286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_large_nrequests)}
399234370Sjasone};
400234370Sjasone
401286866Sjasonestatic const ctl_named_node_t stats_arenas_i_huge_node[] = {
402286866Sjasone	{NAME("allocated"),	CTL(stats_arenas_i_huge_allocated)},
403286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_huge_nmalloc)},
404286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_huge_ndalloc)},
405286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_huge_nrequests)}
406286866Sjasone};
407286866Sjasone
408235238Sjasonestatic const ctl_named_node_t stats_arenas_i_bins_j_node[] = {
409286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_bins_j_nmalloc)},
410286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_bins_j_ndalloc)},
411286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_bins_j_nrequests)},
412286866Sjasone	{NAME("curregs"),	CTL(stats_arenas_i_bins_j_curregs)},
413286866Sjasone	{NAME("nfills"),	CTL(stats_arenas_i_bins_j_nfills)},
414286866Sjasone	{NAME("nflushes"),	CTL(stats_arenas_i_bins_j_nflushes)},
415286866Sjasone	{NAME("nruns"),		CTL(stats_arenas_i_bins_j_nruns)},
416286866Sjasone	{NAME("nreruns"),	CTL(stats_arenas_i_bins_j_nreruns)},
417286866Sjasone	{NAME("curruns"),	CTL(stats_arenas_i_bins_j_curruns)}
418234370Sjasone};
419235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {
420286866Sjasone	{NAME(""),		CHILD(named, stats_arenas_i_bins_j)}
421234370Sjasone};
422234370Sjasone
423235238Sjasonestatic const ctl_indexed_node_t stats_arenas_i_bins_node[] = {
424234370Sjasone	{INDEX(stats_arenas_i_bins_j)}
425234370Sjasone};
426234370Sjasone
427235238Sjasonestatic const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {
428286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_lruns_j_nmalloc)},
429286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_lruns_j_ndalloc)},
430286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_lruns_j_nrequests)},
431286866Sjasone	{NAME("curruns"),	CTL(stats_arenas_i_lruns_j_curruns)}
432234370Sjasone};
433235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {
434286866Sjasone	{NAME(""),		CHILD(named, stats_arenas_i_lruns_j)}
435234370Sjasone};
436234370Sjasone
437235238Sjasonestatic const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {
438234370Sjasone	{INDEX(stats_arenas_i_lruns_j)}
439234370Sjasone};
440234370Sjasone
441286866Sjasonestatic const ctl_named_node_t stats_arenas_i_hchunks_j_node[] = {
442286866Sjasone	{NAME("nmalloc"),	CTL(stats_arenas_i_hchunks_j_nmalloc)},
443286866Sjasone	{NAME("ndalloc"),	CTL(stats_arenas_i_hchunks_j_ndalloc)},
444286866Sjasone	{NAME("nrequests"),	CTL(stats_arenas_i_hchunks_j_nrequests)},
445286866Sjasone	{NAME("curhchunks"),	CTL(stats_arenas_i_hchunks_j_curhchunks)}
446286866Sjasone};
447286866Sjasonestatic const ctl_named_node_t super_stats_arenas_i_hchunks_j_node[] = {
448286866Sjasone	{NAME(""),		CHILD(named, stats_arenas_i_hchunks_j)}
449286866Sjasone};
450286866Sjasone
451286866Sjasonestatic const ctl_indexed_node_t stats_arenas_i_hchunks_node[] = {
452286866Sjasone	{INDEX(stats_arenas_i_hchunks_j)}
453286866Sjasone};
454286866Sjasone
455235238Sjasonestatic const ctl_named_node_t stats_arenas_i_node[] = {
456286866Sjasone	{NAME("nthreads"),	CTL(stats_arenas_i_nthreads)},
457286866Sjasone	{NAME("dss"),		CTL(stats_arenas_i_dss)},
458286866Sjasone	{NAME("lg_dirty_mult"),	CTL(stats_arenas_i_lg_dirty_mult)},
459296221Sjasone	{NAME("decay_time"),	CTL(stats_arenas_i_decay_time)},
460286866Sjasone	{NAME("pactive"),	CTL(stats_arenas_i_pactive)},
461286866Sjasone	{NAME("pdirty"),	CTL(stats_arenas_i_pdirty)},
462286866Sjasone	{NAME("mapped"),	CTL(stats_arenas_i_mapped)},
463299587Sjasone	{NAME("retained"),	CTL(stats_arenas_i_retained)},
464286866Sjasone	{NAME("npurge"),	CTL(stats_arenas_i_npurge)},
465286866Sjasone	{NAME("nmadvise"),	CTL(stats_arenas_i_nmadvise)},
466286866Sjasone	{NAME("purged"),	CTL(stats_arenas_i_purged)},
467286866Sjasone	{NAME("metadata"),	CHILD(named, stats_arenas_i_metadata)},
468286866Sjasone	{NAME("small"),		CHILD(named, stats_arenas_i_small)},
469286866Sjasone	{NAME("large"),		CHILD(named, stats_arenas_i_large)},
470286866Sjasone	{NAME("huge"),		CHILD(named, stats_arenas_i_huge)},
471286866Sjasone	{NAME("bins"),		CHILD(indexed, stats_arenas_i_bins)},
472286866Sjasone	{NAME("lruns"),		CHILD(indexed, stats_arenas_i_lruns)},
473286866Sjasone	{NAME("hchunks"),	CHILD(indexed, stats_arenas_i_hchunks)}
474234370Sjasone};
475235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_node[] = {
476286866Sjasone	{NAME(""),		CHILD(named, stats_arenas_i)}
477234370Sjasone};
478234370Sjasone
479235238Sjasonestatic const ctl_indexed_node_t stats_arenas_node[] = {
480234370Sjasone	{INDEX(stats_arenas_i)}
481234370Sjasone};
482234370Sjasone
483235238Sjasonestatic const ctl_named_node_t stats_node[] = {
484286866Sjasone	{NAME("cactive"),	CTL(stats_cactive)},
485286866Sjasone	{NAME("allocated"),	CTL(stats_allocated)},
486286866Sjasone	{NAME("active"),	CTL(stats_active)},
487286866Sjasone	{NAME("metadata"),	CTL(stats_metadata)},
488286866Sjasone	{NAME("resident"),	CTL(stats_resident)},
489286866Sjasone	{NAME("mapped"),	CTL(stats_mapped)},
490299587Sjasone	{NAME("retained"),	CTL(stats_retained)},
491286866Sjasone	{NAME("arenas"),	CHILD(indexed, stats_arenas)}
492234370Sjasone};
493234370Sjasone
494235238Sjasonestatic const ctl_named_node_t	root_node[] = {
495234370Sjasone	{NAME("version"),	CTL(version)},
496234370Sjasone	{NAME("epoch"),		CTL(epoch)},
497235238Sjasone	{NAME("thread"),	CHILD(named, thread)},
498235238Sjasone	{NAME("config"),	CHILD(named, config)},
499235238Sjasone	{NAME("opt"),		CHILD(named, opt)},
500286866Sjasone	{NAME("tcache"),	CHILD(named, tcache)},
501242844Sjasone	{NAME("arena"),		CHILD(indexed, arena)},
502235238Sjasone	{NAME("arenas"),	CHILD(named, arenas)},
503235238Sjasone	{NAME("prof"),		CHILD(named, prof)},
504235238Sjasone	{NAME("stats"),		CHILD(named, stats)}
505234370Sjasone};
506235238Sjasonestatic const ctl_named_node_t super_root_node[] = {
507235238Sjasone	{NAME(""),		CHILD(named, root)}
508234370Sjasone};
509234370Sjasone
510234370Sjasone#undef NAME
511234370Sjasone#undef CHILD
512234370Sjasone#undef CTL
513234370Sjasone#undef INDEX
514234370Sjasone
515234370Sjasone/******************************************************************************/
516234370Sjasone
517234370Sjasonestatic bool
518234370Sjasonectl_arena_init(ctl_arena_stats_t *astats)
519234370Sjasone{
520234370Sjasone
521234370Sjasone	if (astats->lstats == NULL) {
522286866Sjasone		astats->lstats = (malloc_large_stats_t *)a0malloc(nlclasses *
523234370Sjasone		    sizeof(malloc_large_stats_t));
524234370Sjasone		if (astats->lstats == NULL)
525234370Sjasone			return (true);
526234370Sjasone	}
527234370Sjasone
528286866Sjasone	if (astats->hstats == NULL) {
529286866Sjasone		astats->hstats = (malloc_huge_stats_t *)a0malloc(nhclasses *
530286866Sjasone		    sizeof(malloc_huge_stats_t));
531286866Sjasone		if (astats->hstats == NULL)
532286866Sjasone			return (true);
533286866Sjasone	}
534286866Sjasone
535234370Sjasone	return (false);
536234370Sjasone}
537234370Sjasone
538234370Sjasonestatic void
539234370Sjasonectl_arena_clear(ctl_arena_stats_t *astats)
540234370Sjasone{
541234370Sjasone
542296221Sjasone	astats->nthreads = 0;
543242844Sjasone	astats->dss = dss_prec_names[dss_prec_limit];
544286866Sjasone	astats->lg_dirty_mult = -1;
545296221Sjasone	astats->decay_time = -1;
546234370Sjasone	astats->pactive = 0;
547234370Sjasone	astats->pdirty = 0;
548234370Sjasone	if (config_stats) {
549234370Sjasone		memset(&astats->astats, 0, sizeof(arena_stats_t));
550234370Sjasone		astats->allocated_small = 0;
551234370Sjasone		astats->nmalloc_small = 0;
552234370Sjasone		astats->ndalloc_small = 0;
553234370Sjasone		astats->nrequests_small = 0;
554234370Sjasone		memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));
555234370Sjasone		memset(astats->lstats, 0, nlclasses *
556234370Sjasone		    sizeof(malloc_large_stats_t));
557286866Sjasone		memset(astats->hstats, 0, nhclasses *
558286866Sjasone		    sizeof(malloc_huge_stats_t));
559234370Sjasone	}
560234370Sjasone}
561234370Sjasone
562234370Sjasonestatic void
563299587Sjasonectl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_stats_t *cstats, arena_t *arena)
564234370Sjasone{
565234370Sjasone	unsigned i;
566234370Sjasone
567296221Sjasone	if (config_stats) {
568299587Sjasone		arena_stats_merge(tsdn, arena, &cstats->nthreads, &cstats->dss,
569296221Sjasone		    &cstats->lg_dirty_mult, &cstats->decay_time,
570296221Sjasone		    &cstats->pactive, &cstats->pdirty, &cstats->astats,
571296221Sjasone		    cstats->bstats, cstats->lstats, cstats->hstats);
572234370Sjasone
573296221Sjasone		for (i = 0; i < NBINS; i++) {
574296221Sjasone			cstats->allocated_small += cstats->bstats[i].curregs *
575296221Sjasone			    index2size(i);
576296221Sjasone			cstats->nmalloc_small += cstats->bstats[i].nmalloc;
577296221Sjasone			cstats->ndalloc_small += cstats->bstats[i].ndalloc;
578296221Sjasone			cstats->nrequests_small += cstats->bstats[i].nrequests;
579296221Sjasone		}
580296221Sjasone	} else {
581299587Sjasone		arena_basic_stats_merge(tsdn, arena, &cstats->nthreads,
582299587Sjasone		    &cstats->dss, &cstats->lg_dirty_mult, &cstats->decay_time,
583296221Sjasone		    &cstats->pactive, &cstats->pdirty);
584234370Sjasone	}
585234370Sjasone}
586234370Sjasone
587234370Sjasonestatic void
588234370Sjasonectl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)
589234370Sjasone{
590234370Sjasone	unsigned i;
591234370Sjasone
592296221Sjasone	sstats->nthreads += astats->nthreads;
593234370Sjasone	sstats->pactive += astats->pactive;
594234370Sjasone	sstats->pdirty += astats->pdirty;
595234370Sjasone
596296221Sjasone	if (config_stats) {
597296221Sjasone		sstats->astats.mapped += astats->astats.mapped;
598299587Sjasone		sstats->astats.retained += astats->astats.retained;
599296221Sjasone		sstats->astats.npurge += astats->astats.npurge;
600296221Sjasone		sstats->astats.nmadvise += astats->astats.nmadvise;
601296221Sjasone		sstats->astats.purged += astats->astats.purged;
602234370Sjasone
603296221Sjasone		sstats->astats.metadata_mapped +=
604296221Sjasone		    astats->astats.metadata_mapped;
605296221Sjasone		sstats->astats.metadata_allocated +=
606296221Sjasone		    astats->astats.metadata_allocated;
607286866Sjasone
608296221Sjasone		sstats->allocated_small += astats->allocated_small;
609296221Sjasone		sstats->nmalloc_small += astats->nmalloc_small;
610296221Sjasone		sstats->ndalloc_small += astats->ndalloc_small;
611296221Sjasone		sstats->nrequests_small += astats->nrequests_small;
612234370Sjasone
613296221Sjasone		sstats->astats.allocated_large +=
614296221Sjasone		    astats->astats.allocated_large;
615296221Sjasone		sstats->astats.nmalloc_large += astats->astats.nmalloc_large;
616296221Sjasone		sstats->astats.ndalloc_large += astats->astats.ndalloc_large;
617296221Sjasone		sstats->astats.nrequests_large +=
618296221Sjasone		    astats->astats.nrequests_large;
619234370Sjasone
620296221Sjasone		sstats->astats.allocated_huge += astats->astats.allocated_huge;
621296221Sjasone		sstats->astats.nmalloc_huge += astats->astats.nmalloc_huge;
622296221Sjasone		sstats->astats.ndalloc_huge += astats->astats.ndalloc_huge;
623234370Sjasone
624296221Sjasone		for (i = 0; i < NBINS; i++) {
625296221Sjasone			sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
626296221Sjasone			sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
627296221Sjasone			sstats->bstats[i].nrequests +=
628296221Sjasone			    astats->bstats[i].nrequests;
629296221Sjasone			sstats->bstats[i].curregs += astats->bstats[i].curregs;
630296221Sjasone			if (config_tcache) {
631296221Sjasone				sstats->bstats[i].nfills +=
632296221Sjasone				    astats->bstats[i].nfills;
633296221Sjasone				sstats->bstats[i].nflushes +=
634296221Sjasone				    astats->bstats[i].nflushes;
635296221Sjasone			}
636296221Sjasone			sstats->bstats[i].nruns += astats->bstats[i].nruns;
637296221Sjasone			sstats->bstats[i].reruns += astats->bstats[i].reruns;
638296221Sjasone			sstats->bstats[i].curruns += astats->bstats[i].curruns;
639234370Sjasone		}
640286866Sjasone
641296221Sjasone		for (i = 0; i < nlclasses; i++) {
642296221Sjasone			sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;
643296221Sjasone			sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;
644296221Sjasone			sstats->lstats[i].nrequests +=
645296221Sjasone			    astats->lstats[i].nrequests;
646296221Sjasone			sstats->lstats[i].curruns += astats->lstats[i].curruns;
647296221Sjasone		}
648286866Sjasone
649296221Sjasone		for (i = 0; i < nhclasses; i++) {
650296221Sjasone			sstats->hstats[i].nmalloc += astats->hstats[i].nmalloc;
651296221Sjasone			sstats->hstats[i].ndalloc += astats->hstats[i].ndalloc;
652296221Sjasone			sstats->hstats[i].curhchunks +=
653296221Sjasone			    astats->hstats[i].curhchunks;
654296221Sjasone		}
655286866Sjasone	}
656234370Sjasone}
657234370Sjasone
658234370Sjasonestatic void
659299587Sjasonectl_arena_refresh(tsdn_t *tsdn, arena_t *arena, unsigned i)
660234370Sjasone{
661234370Sjasone	ctl_arena_stats_t *astats = &ctl_stats.arenas[i];
662242844Sjasone	ctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas];
663234370Sjasone
664234370Sjasone	ctl_arena_clear(astats);
665299587Sjasone	ctl_arena_stats_amerge(tsdn, astats, arena);
666296221Sjasone	/* Merge into sum stats as well. */
667296221Sjasone	ctl_arena_stats_smerge(sstats, astats);
668234370Sjasone}
669234370Sjasone
670242844Sjasonestatic bool
671299587Sjasonectl_grow(tsdn_t *tsdn)
672242844Sjasone{
673242844Sjasone	ctl_arena_stats_t *astats;
674242844Sjasone
675286866Sjasone	/* Initialize new arena. */
676299587Sjasone	if (arena_init(tsdn, ctl_stats.narenas) == NULL)
677286866Sjasone		return (true);
678286866Sjasone
679286866Sjasone	/* Allocate extended arena stats. */
680286866Sjasone	astats = (ctl_arena_stats_t *)a0malloc((ctl_stats.narenas + 2) *
681256823Sjasone	    sizeof(ctl_arena_stats_t));
682256823Sjasone	if (astats == NULL)
683256823Sjasone		return (true);
684242844Sjasone
685256823Sjasone	/* Initialize the new astats element. */
686256823Sjasone	memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) *
687256823Sjasone	    sizeof(ctl_arena_stats_t));
688242844Sjasone	memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t));
689256823Sjasone	if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) {
690286866Sjasone		a0dalloc(astats);
691242844Sjasone		return (true);
692256823Sjasone	}
693242844Sjasone	/* Swap merged stats to their new location. */
694242844Sjasone	{
695242844Sjasone		ctl_arena_stats_t tstats;
696242844Sjasone		memcpy(&tstats, &astats[ctl_stats.narenas],
697242844Sjasone		    sizeof(ctl_arena_stats_t));
698242844Sjasone		memcpy(&astats[ctl_stats.narenas],
699242844Sjasone		    &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t));
700242844Sjasone		memcpy(&astats[ctl_stats.narenas + 1], &tstats,
701242844Sjasone		    sizeof(ctl_arena_stats_t));
702242844Sjasone	}
703286866Sjasone	a0dalloc(ctl_stats.arenas);
704242844Sjasone	ctl_stats.arenas = astats;
705242844Sjasone	ctl_stats.narenas++;
706242844Sjasone
707242844Sjasone	return (false);
708242844Sjasone}
709242844Sjasone
710234370Sjasonestatic void
711299587Sjasonectl_refresh(tsdn_t *tsdn)
712234370Sjasone{
713234370Sjasone	unsigned i;
714242844Sjasone	VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);
715234370Sjasone
716234370Sjasone	/*
717234370Sjasone	 * Clear sum stats, since they will be merged into by
718234370Sjasone	 * ctl_arena_refresh().
719234370Sjasone	 */
720242844Sjasone	ctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]);
721234370Sjasone
722296221Sjasone	for (i = 0; i < ctl_stats.narenas; i++)
723299587Sjasone		tarenas[i] = arena_get(tsdn, i, false);
724286866Sjasone
725242844Sjasone	for (i = 0; i < ctl_stats.narenas; i++) {
726234370Sjasone		bool initialized = (tarenas[i] != NULL);
727234370Sjasone
728234370Sjasone		ctl_stats.arenas[i].initialized = initialized;
729234370Sjasone		if (initialized)
730299587Sjasone			ctl_arena_refresh(tsdn, tarenas[i], i);
731234370Sjasone	}
732234370Sjasone
733234370Sjasone	if (config_stats) {
734286866Sjasone		size_t base_allocated, base_resident, base_mapped;
735299587Sjasone		base_stats_get(tsdn, &base_allocated, &base_resident,
736299587Sjasone		    &base_mapped);
737242844Sjasone		ctl_stats.allocated =
738286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].allocated_small +
739286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large +
740286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_huge;
741242844Sjasone		ctl_stats.active =
742286866Sjasone		    (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE);
743286866Sjasone		ctl_stats.metadata = base_allocated +
744286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +
745286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats
746286866Sjasone		    .metadata_allocated;
747286866Sjasone		ctl_stats.resident = base_resident +
748286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +
749286866Sjasone		    ((ctl_stats.arenas[ctl_stats.narenas].pactive +
750286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].pdirty) << LG_PAGE);
751286866Sjasone		ctl_stats.mapped = base_mapped +
752286866Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.mapped;
753299587Sjasone		ctl_stats.retained =
754299587Sjasone		    ctl_stats.arenas[ctl_stats.narenas].astats.retained;
755234370Sjasone	}
756234370Sjasone
757234370Sjasone	ctl_epoch++;
758234370Sjasone}
759234370Sjasone
760234370Sjasonestatic bool
761299587Sjasonectl_init(tsdn_t *tsdn)
762234370Sjasone{
763234370Sjasone	bool ret;
764234370Sjasone
765299587Sjasone	malloc_mutex_lock(tsdn, &ctl_mtx);
766286866Sjasone	if (!ctl_initialized) {
767234370Sjasone		/*
768234370Sjasone		 * Allocate space for one extra arena stats element, which
769234370Sjasone		 * contains summed stats across all arenas.
770234370Sjasone		 */
771286866Sjasone		ctl_stats.narenas = narenas_total_get();
772286866Sjasone		ctl_stats.arenas = (ctl_arena_stats_t *)a0malloc(
773242844Sjasone		    (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t));
774234370Sjasone		if (ctl_stats.arenas == NULL) {
775234370Sjasone			ret = true;
776234370Sjasone			goto label_return;
777234370Sjasone		}
778242844Sjasone		memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) *
779234370Sjasone		    sizeof(ctl_arena_stats_t));
780234370Sjasone
781234370Sjasone		/*
782234370Sjasone		 * Initialize all stats structures, regardless of whether they
783234370Sjasone		 * ever get used.  Lazy initialization would allow errors to
784234370Sjasone		 * cause inconsistent state to be viewable by the application.
785234370Sjasone		 */
786234370Sjasone		if (config_stats) {
787234370Sjasone			unsigned i;
788242844Sjasone			for (i = 0; i <= ctl_stats.narenas; i++) {
789234370Sjasone				if (ctl_arena_init(&ctl_stats.arenas[i])) {
790286866Sjasone					unsigned j;
791286866Sjasone					for (j = 0; j < i; j++) {
792286866Sjasone						a0dalloc(
793286866Sjasone						    ctl_stats.arenas[j].lstats);
794286866Sjasone						a0dalloc(
795286866Sjasone						    ctl_stats.arenas[j].hstats);
796286866Sjasone					}
797286866Sjasone					a0dalloc(ctl_stats.arenas);
798286866Sjasone					ctl_stats.arenas = NULL;
799234370Sjasone					ret = true;
800234370Sjasone					goto label_return;
801234370Sjasone				}
802234370Sjasone			}
803234370Sjasone		}
804242844Sjasone		ctl_stats.arenas[ctl_stats.narenas].initialized = true;
805234370Sjasone
806234370Sjasone		ctl_epoch = 0;
807299587Sjasone		ctl_refresh(tsdn);
808234370Sjasone		ctl_initialized = true;
809234370Sjasone	}
810234370Sjasone
811234370Sjasone	ret = false;
812234370Sjasonelabel_return:
813299587Sjasone	malloc_mutex_unlock(tsdn, &ctl_mtx);
814234370Sjasone	return (ret);
815234370Sjasone}
816234370Sjasone
817234370Sjasonestatic int
818299587Sjasonectl_lookup(tsdn_t *tsdn, const char *name, ctl_node_t const **nodesp,
819299587Sjasone    size_t *mibp, size_t *depthp)
820234370Sjasone{
821234370Sjasone	int ret;
822234370Sjasone	const char *elm, *tdot, *dot;
823234370Sjasone	size_t elen, i, j;
824235238Sjasone	const ctl_named_node_t *node;
825234370Sjasone
826234370Sjasone	elm = name;
827234370Sjasone	/* Equivalent to strchrnul(). */
828234370Sjasone	dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
829234370Sjasone	elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
830234370Sjasone	if (elen == 0) {
831234370Sjasone		ret = ENOENT;
832234370Sjasone		goto label_return;
833234370Sjasone	}
834234370Sjasone	node = super_root_node;
835234370Sjasone	for (i = 0; i < *depthp; i++) {
836235238Sjasone		assert(node);
837235238Sjasone		assert(node->nchildren > 0);
838235238Sjasone		if (ctl_named_node(node->children) != NULL) {
839235238Sjasone			const ctl_named_node_t *pnode = node;
840234370Sjasone
841234370Sjasone			/* Children are named. */
842235238Sjasone			for (j = 0; j < node->nchildren; j++) {
843235238Sjasone				const ctl_named_node_t *child =
844235238Sjasone				    ctl_named_children(node, j);
845235238Sjasone				if (strlen(child->name) == elen &&
846235238Sjasone				    strncmp(elm, child->name, elen) == 0) {
847234370Sjasone					node = child;
848234370Sjasone					if (nodesp != NULL)
849235238Sjasone						nodesp[i] =
850235238Sjasone						    (const ctl_node_t *)node;
851234370Sjasone					mibp[i] = j;
852234370Sjasone					break;
853234370Sjasone				}
854234370Sjasone			}
855234370Sjasone			if (node == pnode) {
856234370Sjasone				ret = ENOENT;
857234370Sjasone				goto label_return;
858234370Sjasone			}
859234370Sjasone		} else {
860234370Sjasone			uintmax_t index;
861235238Sjasone			const ctl_indexed_node_t *inode;
862234370Sjasone
863234370Sjasone			/* Children are indexed. */
864234370Sjasone			index = malloc_strtoumax(elm, NULL, 10);
865234370Sjasone			if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
866234370Sjasone				ret = ENOENT;
867234370Sjasone				goto label_return;
868234370Sjasone			}
869234370Sjasone
870235238Sjasone			inode = ctl_indexed_node(node->children);
871299587Sjasone			node = inode->index(tsdn, mibp, *depthp, (size_t)index);
872234370Sjasone			if (node == NULL) {
873234370Sjasone				ret = ENOENT;
874234370Sjasone				goto label_return;
875234370Sjasone			}
876234370Sjasone
877234370Sjasone			if (nodesp != NULL)
878235238Sjasone				nodesp[i] = (const ctl_node_t *)node;
879234370Sjasone			mibp[i] = (size_t)index;
880234370Sjasone		}
881234370Sjasone
882234370Sjasone		if (node->ctl != NULL) {
883234370Sjasone			/* Terminal node. */
884234370Sjasone			if (*dot != '\0') {
885234370Sjasone				/*
886234370Sjasone				 * The name contains more elements than are
887234370Sjasone				 * in this path through the tree.
888234370Sjasone				 */
889234370Sjasone				ret = ENOENT;
890234370Sjasone				goto label_return;
891234370Sjasone			}
892234370Sjasone			/* Complete lookup successful. */
893234370Sjasone			*depthp = i + 1;
894234370Sjasone			break;
895234370Sjasone		}
896234370Sjasone
897234370Sjasone		/* Update elm. */
898234370Sjasone		if (*dot == '\0') {
899234370Sjasone			/* No more elements. */
900234370Sjasone			ret = ENOENT;
901234370Sjasone			goto label_return;
902234370Sjasone		}
903234370Sjasone		elm = &dot[1];
904234370Sjasone		dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
905234370Sjasone		    strchr(elm, '\0');
906234370Sjasone		elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
907234370Sjasone	}
908234370Sjasone
909234370Sjasone	ret = 0;
910234370Sjasonelabel_return:
911234370Sjasone	return (ret);
912234370Sjasone}
913234370Sjasone
914234370Sjasoneint
915299587Sjasonectl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp,
916299587Sjasone    void *newp, size_t newlen)
917234370Sjasone{
918234370Sjasone	int ret;
919234370Sjasone	size_t depth;
920234370Sjasone	ctl_node_t const *nodes[CTL_MAX_DEPTH];
921234370Sjasone	size_t mib[CTL_MAX_DEPTH];
922235238Sjasone	const ctl_named_node_t *node;
923234370Sjasone
924299587Sjasone	if (!ctl_initialized && ctl_init(tsd_tsdn(tsd))) {
925234370Sjasone		ret = EAGAIN;
926234370Sjasone		goto label_return;
927234370Sjasone	}
928234370Sjasone
929234370Sjasone	depth = CTL_MAX_DEPTH;
930299587Sjasone	ret = ctl_lookup(tsd_tsdn(tsd), name, nodes, mib, &depth);
931234370Sjasone	if (ret != 0)
932234370Sjasone		goto label_return;
933234370Sjasone
934235238Sjasone	node = ctl_named_node(nodes[depth-1]);
935235238Sjasone	if (node != NULL && node->ctl)
936299587Sjasone		ret = node->ctl(tsd, mib, depth, oldp, oldlenp, newp, newlen);
937235238Sjasone	else {
938234370Sjasone		/* The name refers to a partial path through the ctl tree. */
939234370Sjasone		ret = ENOENT;
940234370Sjasone	}
941234370Sjasone
942234370Sjasonelabel_return:
943234370Sjasone	return(ret);
944234370Sjasone}
945234370Sjasone
946234370Sjasoneint
947299587Sjasonectl_nametomib(tsdn_t *tsdn, const char *name, size_t *mibp, size_t *miblenp)
948234370Sjasone{
949234370Sjasone	int ret;
950234370Sjasone
951299587Sjasone	if (!ctl_initialized && ctl_init(tsdn)) {
952234370Sjasone		ret = EAGAIN;
953234370Sjasone		goto label_return;
954234370Sjasone	}
955234370Sjasone
956299587Sjasone	ret = ctl_lookup(tsdn, name, NULL, mibp, miblenp);
957234370Sjasonelabel_return:
958234370Sjasone	return(ret);
959234370Sjasone}
960234370Sjasone
961234370Sjasoneint
962299587Sjasonectl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
963299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
964234370Sjasone{
965234370Sjasone	int ret;
966235238Sjasone	const ctl_named_node_t *node;
967234370Sjasone	size_t i;
968234370Sjasone
969299587Sjasone	if (!ctl_initialized && ctl_init(tsd_tsdn(tsd))) {
970234370Sjasone		ret = EAGAIN;
971234370Sjasone		goto label_return;
972234370Sjasone	}
973234370Sjasone
974234370Sjasone	/* Iterate down the tree. */
975234370Sjasone	node = super_root_node;
976234370Sjasone	for (i = 0; i < miblen; i++) {
977235238Sjasone		assert(node);
978235238Sjasone		assert(node->nchildren > 0);
979235238Sjasone		if (ctl_named_node(node->children) != NULL) {
980234370Sjasone			/* Children are named. */
981296221Sjasone			if (node->nchildren <= (unsigned)mib[i]) {
982234370Sjasone				ret = ENOENT;
983234370Sjasone				goto label_return;
984234370Sjasone			}
985235238Sjasone			node = ctl_named_children(node, mib[i]);
986234370Sjasone		} else {
987235238Sjasone			const ctl_indexed_node_t *inode;
988234370Sjasone
989234370Sjasone			/* Indexed element. */
990235238Sjasone			inode = ctl_indexed_node(node->children);
991299587Sjasone			node = inode->index(tsd_tsdn(tsd), mib, miblen, mib[i]);
992234370Sjasone			if (node == NULL) {
993234370Sjasone				ret = ENOENT;
994234370Sjasone				goto label_return;
995234370Sjasone			}
996234370Sjasone		}
997234370Sjasone	}
998234370Sjasone
999234370Sjasone	/* Call the ctl function. */
1000235238Sjasone	if (node && node->ctl)
1001299587Sjasone		ret = node->ctl(tsd, mib, miblen, oldp, oldlenp, newp, newlen);
1002235238Sjasone	else {
1003234370Sjasone		/* Partial MIB. */
1004234370Sjasone		ret = ENOENT;
1005234370Sjasone	}
1006234370Sjasone
1007234370Sjasonelabel_return:
1008234370Sjasone	return(ret);
1009234370Sjasone}
1010234370Sjasone
1011234370Sjasonebool
1012234370Sjasonectl_boot(void)
1013234370Sjasone{
1014234370Sjasone
1015299587Sjasone	if (malloc_mutex_init(&ctl_mtx, "ctl", WITNESS_RANK_CTL))
1016234370Sjasone		return (true);
1017234370Sjasone
1018234370Sjasone	ctl_initialized = false;
1019234370Sjasone
1020234370Sjasone	return (false);
1021234370Sjasone}
1022234370Sjasone
1023242844Sjasonevoid
1024299587Sjasonectl_prefork(tsdn_t *tsdn)
1025242844Sjasone{
1026242844Sjasone
1027299587Sjasone	malloc_mutex_prefork(tsdn, &ctl_mtx);
1028242844Sjasone}
1029242844Sjasone
1030242844Sjasonevoid
1031299587Sjasonectl_postfork_parent(tsdn_t *tsdn)
1032242844Sjasone{
1033242844Sjasone
1034299587Sjasone	malloc_mutex_postfork_parent(tsdn, &ctl_mtx);
1035242844Sjasone}
1036242844Sjasone
1037242844Sjasonevoid
1038299587Sjasonectl_postfork_child(tsdn_t *tsdn)
1039242844Sjasone{
1040242844Sjasone
1041299587Sjasone	malloc_mutex_postfork_child(tsdn, &ctl_mtx);
1042242844Sjasone}
1043242844Sjasone
1044234370Sjasone/******************************************************************************/
1045234370Sjasone/* *_ctl() functions. */
1046234370Sjasone
1047234370Sjasone#define	READONLY()	do {						\
1048234370Sjasone	if (newp != NULL || newlen != 0) {				\
1049234370Sjasone		ret = EPERM;						\
1050235238Sjasone		goto label_return;					\
1051234370Sjasone	}								\
1052234370Sjasone} while (0)
1053234370Sjasone
1054234370Sjasone#define	WRITEONLY()	do {						\
1055234370Sjasone	if (oldp != NULL || oldlenp != NULL) {				\
1056234370Sjasone		ret = EPERM;						\
1057235238Sjasone		goto label_return;					\
1058234370Sjasone	}								\
1059234370Sjasone} while (0)
1060234370Sjasone
1061286866Sjasone#define	READ_XOR_WRITE()	do {					\
1062286866Sjasone	if ((oldp != NULL && oldlenp != NULL) && (newp != NULL ||	\
1063286866Sjasone	    newlen != 0)) {						\
1064286866Sjasone		ret = EPERM;						\
1065286866Sjasone		goto label_return;					\
1066286866Sjasone	}								\
1067286866Sjasone} while (0)
1068286866Sjasone
1069234370Sjasone#define	READ(v, t)	do {						\
1070234370Sjasone	if (oldp != NULL && oldlenp != NULL) {				\
1071234370Sjasone		if (*oldlenp != sizeof(t)) {				\
1072234370Sjasone			size_t	copylen = (sizeof(t) <= *oldlenp)	\
1073234370Sjasone			    ? sizeof(t) : *oldlenp;			\
1074245868Sjasone			memcpy(oldp, (void *)&(v), copylen);		\
1075234370Sjasone			ret = EINVAL;					\
1076235238Sjasone			goto label_return;				\
1077286866Sjasone		}							\
1078286866Sjasone		*(t *)oldp = (v);					\
1079234370Sjasone	}								\
1080234370Sjasone} while (0)
1081234370Sjasone
1082234370Sjasone#define	WRITE(v, t)	do {						\
1083234370Sjasone	if (newp != NULL) {						\
1084234370Sjasone		if (newlen != sizeof(t)) {				\
1085234370Sjasone			ret = EINVAL;					\
1086235238Sjasone			goto label_return;				\
1087234370Sjasone		}							\
1088245868Sjasone		(v) = *(t *)newp;					\
1089234370Sjasone	}								\
1090234370Sjasone} while (0)
1091234370Sjasone
1092234370Sjasone/*
1093234370Sjasone * There's a lot of code duplication in the following macros due to limitations
1094234370Sjasone * in how nested cpp macros are expanded.
1095234370Sjasone */
1096234370Sjasone#define	CTL_RO_CLGEN(c, l, n, v, t)					\
1097234370Sjasonestatic int								\
1098299587Sjasonen##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
1099299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)				\
1100234370Sjasone{									\
1101234370Sjasone	int ret;							\
1102234370Sjasone	t oldval;							\
1103234370Sjasone									\
1104286866Sjasone	if (!(c))							\
1105234370Sjasone		return (ENOENT);					\
1106234370Sjasone	if (l)								\
1107299587Sjasone		malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);		\
1108234370Sjasone	READONLY();							\
1109245868Sjasone	oldval = (v);							\
1110234370Sjasone	READ(oldval, t);						\
1111234370Sjasone									\
1112234370Sjasone	ret = 0;							\
1113235238Sjasonelabel_return:								\
1114234370Sjasone	if (l)								\
1115299587Sjasone		malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);		\
1116234370Sjasone	return (ret);							\
1117234370Sjasone}
1118234370Sjasone
1119234370Sjasone#define	CTL_RO_CGEN(c, n, v, t)						\
1120234370Sjasonestatic int								\
1121299587Sjasonen##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
1122299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)				\
1123234370Sjasone{									\
1124234370Sjasone	int ret;							\
1125234370Sjasone	t oldval;							\
1126234370Sjasone									\
1127286866Sjasone	if (!(c))							\
1128234370Sjasone		return (ENOENT);					\
1129299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);			\
1130234370Sjasone	READONLY();							\
1131245868Sjasone	oldval = (v);							\
1132234370Sjasone	READ(oldval, t);						\
1133234370Sjasone									\
1134234370Sjasone	ret = 0;							\
1135235238Sjasonelabel_return:								\
1136299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);			\
1137234370Sjasone	return (ret);							\
1138234370Sjasone}
1139234370Sjasone
1140234370Sjasone#define	CTL_RO_GEN(n, v, t)						\
1141234370Sjasonestatic int								\
1142299587Sjasonen##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
1143299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)				\
1144234370Sjasone{									\
1145234370Sjasone	int ret;							\
1146234370Sjasone	t oldval;							\
1147234370Sjasone									\
1148299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);			\
1149234370Sjasone	READONLY();							\
1150245868Sjasone	oldval = (v);							\
1151234370Sjasone	READ(oldval, t);						\
1152234370Sjasone									\
1153234370Sjasone	ret = 0;							\
1154235238Sjasonelabel_return:								\
1155299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);			\
1156234370Sjasone	return (ret);							\
1157234370Sjasone}
1158234370Sjasone
1159234370Sjasone/*
1160234370Sjasone * ctl_mtx is not acquired, under the assumption that no pertinent data will
1161234370Sjasone * mutate during the call.
1162234370Sjasone */
1163234370Sjasone#define	CTL_RO_NL_CGEN(c, n, v, t)					\
1164234370Sjasonestatic int								\
1165299587Sjasonen##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
1166299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)				\
1167234370Sjasone{									\
1168234370Sjasone	int ret;							\
1169234370Sjasone	t oldval;							\
1170234370Sjasone									\
1171286866Sjasone	if (!(c))							\
1172234370Sjasone		return (ENOENT);					\
1173234370Sjasone	READONLY();							\
1174245868Sjasone	oldval = (v);							\
1175234370Sjasone	READ(oldval, t);						\
1176234370Sjasone									\
1177234370Sjasone	ret = 0;							\
1178235238Sjasonelabel_return:								\
1179234370Sjasone	return (ret);							\
1180234370Sjasone}
1181234370Sjasone
1182234370Sjasone#define	CTL_RO_NL_GEN(n, v, t)						\
1183234370Sjasonestatic int								\
1184299587Sjasonen##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
1185299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)				\
1186234370Sjasone{									\
1187234370Sjasone	int ret;							\
1188234370Sjasone	t oldval;							\
1189234370Sjasone									\
1190234370Sjasone	READONLY();							\
1191245868Sjasone	oldval = (v);							\
1192234370Sjasone	READ(oldval, t);						\
1193234370Sjasone									\
1194234370Sjasone	ret = 0;							\
1195235238Sjasonelabel_return:								\
1196234370Sjasone	return (ret);							\
1197234370Sjasone}
1198234370Sjasone
1199286866Sjasone#define	CTL_TSD_RO_NL_CGEN(c, n, m, t)					\
1200286866Sjasonestatic int								\
1201299587Sjasonen##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
1202299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)				\
1203286866Sjasone{									\
1204286866Sjasone	int ret;							\
1205286866Sjasone	t oldval;							\
1206286866Sjasone									\
1207286866Sjasone	if (!(c))							\
1208286866Sjasone		return (ENOENT);					\
1209286866Sjasone	READONLY();							\
1210286866Sjasone	oldval = (m(tsd));						\
1211286866Sjasone	READ(oldval, t);						\
1212286866Sjasone									\
1213286866Sjasone	ret = 0;							\
1214286866Sjasonelabel_return:								\
1215286866Sjasone	return (ret);							\
1216286866Sjasone}
1217286866Sjasone
1218296221Sjasone#define	CTL_RO_CONFIG_GEN(n, t)						\
1219234370Sjasonestatic int								\
1220299587Sjasonen##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
1221299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)				\
1222234370Sjasone{									\
1223234370Sjasone	int ret;							\
1224296221Sjasone	t oldval;							\
1225234370Sjasone									\
1226234370Sjasone	READONLY();							\
1227234370Sjasone	oldval = n;							\
1228296221Sjasone	READ(oldval, t);						\
1229234370Sjasone									\
1230234370Sjasone	ret = 0;							\
1231235238Sjasonelabel_return:								\
1232234370Sjasone	return (ret);							\
1233234370Sjasone}
1234234370Sjasone
1235261071Sjasone/******************************************************************************/
1236261071Sjasone
1237234370SjasoneCTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
1238234370Sjasone
1239234370Sjasonestatic int
1240299587Sjasoneepoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1241299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1242234370Sjasone{
1243234370Sjasone	int ret;
1244256823Sjasone	UNUSED uint64_t newval;
1245234370Sjasone
1246299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1247234370Sjasone	WRITE(newval, uint64_t);
1248235238Sjasone	if (newp != NULL)
1249299587Sjasone		ctl_refresh(tsd_tsdn(tsd));
1250234370Sjasone	READ(ctl_epoch, uint64_t);
1251234370Sjasone
1252234370Sjasone	ret = 0;
1253234370Sjasonelabel_return:
1254299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1255234370Sjasone	return (ret);
1256234370Sjasone}
1257234370Sjasone
1258261071Sjasone/******************************************************************************/
1259234370Sjasone
1260296221SjasoneCTL_RO_CONFIG_GEN(config_cache_oblivious, bool)
1261296221SjasoneCTL_RO_CONFIG_GEN(config_debug, bool)
1262296221SjasoneCTL_RO_CONFIG_GEN(config_fill, bool)
1263296221SjasoneCTL_RO_CONFIG_GEN(config_lazy_lock, bool)
1264296221SjasoneCTL_RO_CONFIG_GEN(config_malloc_conf, const char *)
1265296221SjasoneCTL_RO_CONFIG_GEN(config_munmap, bool)
1266296221SjasoneCTL_RO_CONFIG_GEN(config_prof, bool)
1267296221SjasoneCTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
1268296221SjasoneCTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
1269296221SjasoneCTL_RO_CONFIG_GEN(config_stats, bool)
1270296221SjasoneCTL_RO_CONFIG_GEN(config_tcache, bool)
1271296221SjasoneCTL_RO_CONFIG_GEN(config_tls, bool)
1272296221SjasoneCTL_RO_CONFIG_GEN(config_utrace, bool)
1273296221SjasoneCTL_RO_CONFIG_GEN(config_valgrind, bool)
1274296221SjasoneCTL_RO_CONFIG_GEN(config_xmalloc, bool)
1275234370Sjasone
1276261071Sjasone/******************************************************************************/
1277234370Sjasone
1278261071SjasoneCTL_RO_NL_GEN(opt_abort, opt_abort, bool)
1279261071SjasoneCTL_RO_NL_GEN(opt_dss, opt_dss, const char *)
1280261071SjasoneCTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
1281296221SjasoneCTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned)
1282296221SjasoneCTL_RO_NL_GEN(opt_purge, purge_mode_names[opt_purge], const char *)
1283261071SjasoneCTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
1284296221SjasoneCTL_RO_NL_GEN(opt_decay_time, opt_decay_time, ssize_t)
1285261071SjasoneCTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
1286286866SjasoneCTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)
1287261071SjasoneCTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
1288261071SjasoneCTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
1289261071SjasoneCTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
1290261071SjasoneCTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
1291261071SjasoneCTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
1292261071SjasoneCTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
1293261071SjasoneCTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
1294261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
1295261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
1296286866SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool)
1297286866SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
1298286866Sjasone    opt_prof_thread_active_init, bool)
1299261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
1300261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
1301261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
1302261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
1303261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
1304261071SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
1305234370Sjasone
1306261071Sjasone/******************************************************************************/
1307234370Sjasone
1308234370Sjasonestatic int
1309299587Sjasonethread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1310299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1311234370Sjasone{
1312234370Sjasone	int ret;
1313286866Sjasone	arena_t *oldarena;
1314234370Sjasone	unsigned newind, oldind;
1315234370Sjasone
1316286866Sjasone	oldarena = arena_choose(tsd, NULL);
1317286866Sjasone	if (oldarena == NULL)
1318286866Sjasone		return (EAGAIN);
1319286866Sjasone
1320299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1321286866Sjasone	newind = oldind = oldarena->ind;
1322234370Sjasone	WRITE(newind, unsigned);
1323234370Sjasone	READ(oldind, unsigned);
1324234370Sjasone	if (newind != oldind) {
1325286866Sjasone		arena_t *newarena;
1326234370Sjasone
1327242844Sjasone		if (newind >= ctl_stats.narenas) {
1328234370Sjasone			/* New arena index is out of range. */
1329234370Sjasone			ret = EFAULT;
1330234370Sjasone			goto label_return;
1331234370Sjasone		}
1332234370Sjasone
1333234370Sjasone		/* Initialize arena if necessary. */
1334299587Sjasone		newarena = arena_get(tsd_tsdn(tsd), newind, true);
1335286866Sjasone		if (newarena == NULL) {
1336234370Sjasone			ret = EAGAIN;
1337234370Sjasone			goto label_return;
1338234370Sjasone		}
1339286866Sjasone		/* Set new arena/tcache associations. */
1340286866Sjasone		arena_migrate(tsd, oldind, newind);
1341234370Sjasone		if (config_tcache) {
1342286866Sjasone			tcache_t *tcache = tsd_tcache_get(tsd);
1343286866Sjasone			if (tcache != NULL) {
1344299587Sjasone				tcache_arena_reassociate(tsd_tsdn(tsd), tcache,
1345299587Sjasone				    oldarena, newarena);
1346234370Sjasone			}
1347234370Sjasone		}
1348234370Sjasone	}
1349234370Sjasone
1350234370Sjasone	ret = 0;
1351234370Sjasonelabel_return:
1352299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1353234370Sjasone	return (ret);
1354234370Sjasone}
1355234370Sjasone
1356286866SjasoneCTL_TSD_RO_NL_CGEN(config_stats, thread_allocated, tsd_thread_allocated_get,
1357286866Sjasone    uint64_t)
1358286866SjasoneCTL_TSD_RO_NL_CGEN(config_stats, thread_allocatedp, tsd_thread_allocatedp_get,
1359286866Sjasone    uint64_t *)
1360286866SjasoneCTL_TSD_RO_NL_CGEN(config_stats, thread_deallocated, tsd_thread_deallocated_get,
1361286866Sjasone    uint64_t)
1362286866SjasoneCTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp,
1363286866Sjasone    tsd_thread_deallocatedp_get, uint64_t *)
1364234370Sjasone
1365261071Sjasonestatic int
1366299587Sjasonethread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1367299587Sjasone    void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1368261071Sjasone{
1369261071Sjasone	int ret;
1370261071Sjasone	bool oldval;
1371234370Sjasone
1372286866Sjasone	if (!config_tcache)
1373261071Sjasone		return (ENOENT);
1374234370Sjasone
1375261071Sjasone	oldval = tcache_enabled_get();
1376261071Sjasone	if (newp != NULL) {
1377261071Sjasone		if (newlen != sizeof(bool)) {
1378261071Sjasone			ret = EINVAL;
1379261071Sjasone			goto label_return;
1380261071Sjasone		}
1381261071Sjasone		tcache_enabled_set(*(bool *)newp);
1382261071Sjasone	}
1383261071Sjasone	READ(oldval, bool);
1384234370Sjasone
1385261071Sjasone	ret = 0;
1386261071Sjasonelabel_return:
1387261071Sjasone	return (ret);
1388261071Sjasone}
1389234370Sjasone
1390261071Sjasonestatic int
1391299587Sjasonethread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1392299587Sjasone    void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1393261071Sjasone{
1394261071Sjasone	int ret;
1395261071Sjasone
1396286866Sjasone	if (!config_tcache)
1397261071Sjasone		return (ENOENT);
1398261071Sjasone
1399261071Sjasone	READONLY();
1400261071Sjasone	WRITEONLY();
1401261071Sjasone
1402261071Sjasone	tcache_flush();
1403261071Sjasone
1404261071Sjasone	ret = 0;
1405261071Sjasonelabel_return:
1406261071Sjasone	return (ret);
1407261071Sjasone}
1408261071Sjasone
1409286866Sjasonestatic int
1410299587Sjasonethread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1411286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1412286866Sjasone{
1413286866Sjasone	int ret;
1414286866Sjasone
1415286866Sjasone	if (!config_prof)
1416286866Sjasone		return (ENOENT);
1417286866Sjasone
1418286866Sjasone	READ_XOR_WRITE();
1419286866Sjasone
1420286866Sjasone	if (newp != NULL) {
1421286866Sjasone		if (newlen != sizeof(const char *)) {
1422286866Sjasone			ret = EINVAL;
1423286866Sjasone			goto label_return;
1424286866Sjasone		}
1425286866Sjasone
1426286866Sjasone		if ((ret = prof_thread_name_set(tsd, *(const char **)newp)) !=
1427286866Sjasone		    0)
1428286866Sjasone			goto label_return;
1429286866Sjasone	} else {
1430299587Sjasone		const char *oldname = prof_thread_name_get(tsd);
1431286866Sjasone		READ(oldname, const char *);
1432286866Sjasone	}
1433286866Sjasone
1434286866Sjasone	ret = 0;
1435286866Sjasonelabel_return:
1436286866Sjasone	return (ret);
1437286866Sjasone}
1438286866Sjasone
1439286866Sjasonestatic int
1440299587Sjasonethread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1441286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1442286866Sjasone{
1443286866Sjasone	int ret;
1444286866Sjasone	bool oldval;
1445286866Sjasone
1446286866Sjasone	if (!config_prof)
1447286866Sjasone		return (ENOENT);
1448286866Sjasone
1449299587Sjasone	oldval = prof_thread_active_get(tsd);
1450286866Sjasone	if (newp != NULL) {
1451286866Sjasone		if (newlen != sizeof(bool)) {
1452286866Sjasone			ret = EINVAL;
1453286866Sjasone			goto label_return;
1454286866Sjasone		}
1455299587Sjasone		if (prof_thread_active_set(tsd, *(bool *)newp)) {
1456286866Sjasone			ret = EAGAIN;
1457286866Sjasone			goto label_return;
1458286866Sjasone		}
1459286866Sjasone	}
1460286866Sjasone	READ(oldval, bool);
1461286866Sjasone
1462286866Sjasone	ret = 0;
1463286866Sjasonelabel_return:
1464286866Sjasone	return (ret);
1465286866Sjasone}
1466286866Sjasone
1467234370Sjasone/******************************************************************************/
1468234370Sjasone
1469286866Sjasonestatic int
1470299587Sjasonetcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1471299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1472286866Sjasone{
1473286866Sjasone	int ret;
1474286866Sjasone	unsigned tcache_ind;
1475286866Sjasone
1476286866Sjasone	if (!config_tcache)
1477286866Sjasone		return (ENOENT);
1478286866Sjasone
1479299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1480286866Sjasone	READONLY();
1481299587Sjasone	if (tcaches_create(tsd_tsdn(tsd), &tcache_ind)) {
1482286866Sjasone		ret = EFAULT;
1483286866Sjasone		goto label_return;
1484286866Sjasone	}
1485286866Sjasone	READ(tcache_ind, unsigned);
1486286866Sjasone
1487286866Sjasone	ret = 0;
1488286866Sjasonelabel_return:
1489299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1490286866Sjasone	return (ret);
1491286866Sjasone}
1492286866Sjasone
1493286866Sjasonestatic int
1494299587Sjasonetcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1495299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1496286866Sjasone{
1497286866Sjasone	int ret;
1498286866Sjasone	unsigned tcache_ind;
1499286866Sjasone
1500286866Sjasone	if (!config_tcache)
1501286866Sjasone		return (ENOENT);
1502286866Sjasone
1503286866Sjasone	WRITEONLY();
1504286866Sjasone	tcache_ind = UINT_MAX;
1505286866Sjasone	WRITE(tcache_ind, unsigned);
1506286866Sjasone	if (tcache_ind == UINT_MAX) {
1507286866Sjasone		ret = EFAULT;
1508286866Sjasone		goto label_return;
1509286866Sjasone	}
1510286866Sjasone	tcaches_flush(tsd, tcache_ind);
1511286866Sjasone
1512286866Sjasone	ret = 0;
1513286866Sjasonelabel_return:
1514286866Sjasone	return (ret);
1515286866Sjasone}
1516286866Sjasone
1517286866Sjasonestatic int
1518299587Sjasonetcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1519286866Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1520286866Sjasone{
1521286866Sjasone	int ret;
1522286866Sjasone	unsigned tcache_ind;
1523286866Sjasone
1524286866Sjasone	if (!config_tcache)
1525286866Sjasone		return (ENOENT);
1526286866Sjasone
1527286866Sjasone	WRITEONLY();
1528286866Sjasone	tcache_ind = UINT_MAX;
1529286866Sjasone	WRITE(tcache_ind, unsigned);
1530286866Sjasone	if (tcache_ind == UINT_MAX) {
1531286866Sjasone		ret = EFAULT;
1532286866Sjasone		goto label_return;
1533286866Sjasone	}
1534286866Sjasone	tcaches_destroy(tsd, tcache_ind);
1535286866Sjasone
1536286866Sjasone	ret = 0;
1537286866Sjasonelabel_return:
1538286866Sjasone	return (ret);
1539286866Sjasone}
1540286866Sjasone
1541286866Sjasone/******************************************************************************/
1542286866Sjasone
1543242844Sjasonestatic void
1544299587Sjasonearena_i_purge(tsdn_t *tsdn, unsigned arena_ind, bool all)
1545242844Sjasone{
1546242844Sjasone
1547299587Sjasone	malloc_mutex_lock(tsdn, &ctl_mtx);
1548296221Sjasone	{
1549296221Sjasone		unsigned narenas = ctl_stats.narenas;
1550242844Sjasone
1551296221Sjasone		if (arena_ind == narenas) {
1552296221Sjasone			unsigned i;
1553296221Sjasone			VARIABLE_ARRAY(arena_t *, tarenas, narenas);
1554296221Sjasone
1555296221Sjasone			for (i = 0; i < narenas; i++)
1556299587Sjasone				tarenas[i] = arena_get(tsdn, i, false);
1557296221Sjasone
1558296221Sjasone			/*
1559296221Sjasone			 * No further need to hold ctl_mtx, since narenas and
1560296221Sjasone			 * tarenas contain everything needed below.
1561296221Sjasone			 */
1562299587Sjasone			malloc_mutex_unlock(tsdn, &ctl_mtx);
1563296221Sjasone
1564296221Sjasone			for (i = 0; i < narenas; i++) {
1565296221Sjasone				if (tarenas[i] != NULL)
1566299587Sjasone					arena_purge(tsdn, tarenas[i], all);
1567296221Sjasone			}
1568296221Sjasone		} else {
1569296221Sjasone			arena_t *tarena;
1570296221Sjasone
1571296221Sjasone			assert(arena_ind < narenas);
1572296221Sjasone
1573299587Sjasone			tarena = arena_get(tsdn, arena_ind, false);
1574296221Sjasone
1575296221Sjasone			/* No further need to hold ctl_mtx. */
1576299587Sjasone			malloc_mutex_unlock(tsdn, &ctl_mtx);
1577296221Sjasone
1578296221Sjasone			if (tarena != NULL)
1579299587Sjasone				arena_purge(tsdn, tarena, all);
1580242844Sjasone		}
1581242844Sjasone	}
1582242844Sjasone}
1583242844Sjasone
1584242844Sjasonestatic int
1585299587Sjasonearena_i_purge_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1586299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1587242844Sjasone{
1588242844Sjasone	int ret;
1589242844Sjasone
1590242844Sjasone	READONLY();
1591242844Sjasone	WRITEONLY();
1592299587Sjasone	arena_i_purge(tsd_tsdn(tsd), (unsigned)mib[1], true);
1593242844Sjasone
1594242844Sjasone	ret = 0;
1595242844Sjasonelabel_return:
1596242844Sjasone	return (ret);
1597242844Sjasone}
1598242844Sjasone
1599242844Sjasonestatic int
1600299587Sjasonearena_i_decay_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1601299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1602296221Sjasone{
1603296221Sjasone	int ret;
1604296221Sjasone
1605296221Sjasone	READONLY();
1606296221Sjasone	WRITEONLY();
1607299587Sjasone	arena_i_purge(tsd_tsdn(tsd), (unsigned)mib[1], false);
1608296221Sjasone
1609296221Sjasone	ret = 0;
1610296221Sjasonelabel_return:
1611296221Sjasone	return (ret);
1612296221Sjasone}
1613296221Sjasone
1614296221Sjasonestatic int
1615299587Sjasonearena_i_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1616299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1617242844Sjasone{
1618286866Sjasone	int ret;
1619299587Sjasone	unsigned arena_ind;
1620299587Sjasone	arena_t *arena;
1621299587Sjasone
1622299587Sjasone	READONLY();
1623299587Sjasone	WRITEONLY();
1624299587Sjasone
1625299587Sjasone	if ((config_valgrind && unlikely(in_valgrind)) || (config_fill &&
1626299587Sjasone	    unlikely(opt_quarantine))) {
1627299587Sjasone		ret = EFAULT;
1628299587Sjasone		goto label_return;
1629299587Sjasone	}
1630299587Sjasone
1631299587Sjasone	arena_ind = (unsigned)mib[1];
1632299587Sjasone	if (config_debug) {
1633299587Sjasone		malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1634299587Sjasone		assert(arena_ind < ctl_stats.narenas);
1635299587Sjasone		malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1636299587Sjasone	}
1637299587Sjasone	assert(arena_ind >= opt_narenas);
1638299587Sjasone
1639299587Sjasone	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1640299587Sjasone
1641299587Sjasone	arena_reset(tsd, arena);
1642299587Sjasone
1643299587Sjasone	ret = 0;
1644299587Sjasonelabel_return:
1645299587Sjasone	return (ret);
1646299587Sjasone}
1647299587Sjasone
1648299587Sjasonestatic int
1649299587Sjasonearena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1650299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1651299587Sjasone{
1652299587Sjasone	int ret;
1653286866Sjasone	const char *dss = NULL;
1654296221Sjasone	unsigned arena_ind = (unsigned)mib[1];
1655242844Sjasone	dss_prec_t dss_prec_old = dss_prec_limit;
1656242844Sjasone	dss_prec_t dss_prec = dss_prec_limit;
1657242844Sjasone
1658299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1659242844Sjasone	WRITE(dss, const char *);
1660286866Sjasone	if (dss != NULL) {
1661286866Sjasone		int i;
1662286866Sjasone		bool match = false;
1663286866Sjasone
1664286866Sjasone		for (i = 0; i < dss_prec_limit; i++) {
1665286866Sjasone			if (strcmp(dss_prec_names[i], dss) == 0) {
1666286866Sjasone				dss_prec = i;
1667286866Sjasone				match = true;
1668286866Sjasone				break;
1669286866Sjasone			}
1670242844Sjasone		}
1671286866Sjasone
1672286866Sjasone		if (!match) {
1673286866Sjasone			ret = EINVAL;
1674286866Sjasone			goto label_return;
1675286866Sjasone		}
1676242844Sjasone	}
1677242844Sjasone
1678242844Sjasone	if (arena_ind < ctl_stats.narenas) {
1679299587Sjasone		arena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1680286866Sjasone		if (arena == NULL || (dss_prec != dss_prec_limit &&
1681299587Sjasone		    arena_dss_prec_set(tsd_tsdn(tsd), arena, dss_prec))) {
1682286866Sjasone			ret = EFAULT;
1683286866Sjasone			goto label_return;
1684286866Sjasone		}
1685299587Sjasone		dss_prec_old = arena_dss_prec_get(tsd_tsdn(tsd), arena);
1686242844Sjasone	} else {
1687286866Sjasone		if (dss_prec != dss_prec_limit &&
1688299587Sjasone		    chunk_dss_prec_set(tsd_tsdn(tsd), dss_prec)) {
1689286866Sjasone			ret = EFAULT;
1690286866Sjasone			goto label_return;
1691286866Sjasone		}
1692299587Sjasone		dss_prec_old = chunk_dss_prec_get(tsd_tsdn(tsd));
1693242844Sjasone	}
1694286866Sjasone
1695242844Sjasone	dss = dss_prec_names[dss_prec_old];
1696242844Sjasone	READ(dss, const char *);
1697286866Sjasone
1698286866Sjasone	ret = 0;
1699286866Sjasonelabel_return:
1700299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1701286866Sjasone	return (ret);
1702286866Sjasone}
1703286866Sjasone
1704286866Sjasonestatic int
1705299587Sjasonearena_i_lg_dirty_mult_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1706299587Sjasone    void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1707286866Sjasone{
1708286866Sjasone	int ret;
1709296221Sjasone	unsigned arena_ind = (unsigned)mib[1];
1710286866Sjasone	arena_t *arena;
1711286866Sjasone
1712299587Sjasone	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1713286866Sjasone	if (arena == NULL) {
1714242844Sjasone		ret = EFAULT;
1715242844Sjasone		goto label_return;
1716242844Sjasone	}
1717242844Sjasone
1718286866Sjasone	if (oldp != NULL && oldlenp != NULL) {
1719299587Sjasone		size_t oldval = arena_lg_dirty_mult_get(tsd_tsdn(tsd), arena);
1720286866Sjasone		READ(oldval, ssize_t);
1721286866Sjasone	}
1722286866Sjasone	if (newp != NULL) {
1723286866Sjasone		if (newlen != sizeof(ssize_t)) {
1724286866Sjasone			ret = EINVAL;
1725286866Sjasone			goto label_return;
1726286866Sjasone		}
1727299587Sjasone		if (arena_lg_dirty_mult_set(tsd_tsdn(tsd), arena,
1728299587Sjasone		    *(ssize_t *)newp)) {
1729286866Sjasone			ret = EFAULT;
1730286866Sjasone			goto label_return;
1731286866Sjasone		}
1732286866Sjasone	}
1733286866Sjasone
1734242844Sjasone	ret = 0;
1735242844Sjasonelabel_return:
1736286866Sjasone	return (ret);
1737286866Sjasone}
1738286866Sjasone
1739286866Sjasonestatic int
1740299587Sjasonearena_i_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1741296221Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1742296221Sjasone{
1743296221Sjasone	int ret;
1744296221Sjasone	unsigned arena_ind = (unsigned)mib[1];
1745296221Sjasone	arena_t *arena;
1746296221Sjasone
1747299587Sjasone	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1748296221Sjasone	if (arena == NULL) {
1749296221Sjasone		ret = EFAULT;
1750296221Sjasone		goto label_return;
1751296221Sjasone	}
1752296221Sjasone
1753296221Sjasone	if (oldp != NULL && oldlenp != NULL) {
1754299587Sjasone		size_t oldval = arena_decay_time_get(tsd_tsdn(tsd), arena);
1755296221Sjasone		READ(oldval, ssize_t);
1756296221Sjasone	}
1757296221Sjasone	if (newp != NULL) {
1758296221Sjasone		if (newlen != sizeof(ssize_t)) {
1759296221Sjasone			ret = EINVAL;
1760296221Sjasone			goto label_return;
1761296221Sjasone		}
1762299587Sjasone		if (arena_decay_time_set(tsd_tsdn(tsd), arena,
1763299587Sjasone		    *(ssize_t *)newp)) {
1764296221Sjasone			ret = EFAULT;
1765296221Sjasone			goto label_return;
1766296221Sjasone		}
1767296221Sjasone	}
1768296221Sjasone
1769296221Sjasone	ret = 0;
1770296221Sjasonelabel_return:
1771296221Sjasone	return (ret);
1772296221Sjasone}
1773296221Sjasone
1774296221Sjasonestatic int
1775299587Sjasonearena_i_chunk_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1776299587Sjasone    void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1777286866Sjasone{
1778286866Sjasone	int ret;
1779296221Sjasone	unsigned arena_ind = (unsigned)mib[1];
1780286866Sjasone	arena_t *arena;
1781286866Sjasone
1782299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1783286866Sjasone	if (arena_ind < narenas_total_get() && (arena =
1784299587Sjasone	    arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) {
1785286866Sjasone		if (newp != NULL) {
1786286866Sjasone			chunk_hooks_t old_chunk_hooks, new_chunk_hooks;
1787286866Sjasone			WRITE(new_chunk_hooks, chunk_hooks_t);
1788299587Sjasone			old_chunk_hooks = chunk_hooks_set(tsd_tsdn(tsd), arena,
1789286866Sjasone			    &new_chunk_hooks);
1790286866Sjasone			READ(old_chunk_hooks, chunk_hooks_t);
1791286866Sjasone		} else {
1792299587Sjasone			chunk_hooks_t old_chunk_hooks =
1793299587Sjasone			    chunk_hooks_get(tsd_tsdn(tsd), arena);
1794286866Sjasone			READ(old_chunk_hooks, chunk_hooks_t);
1795286866Sjasone		}
1796286866Sjasone	} else {
1797286866Sjasone		ret = EFAULT;
1798286866Sjasone		goto label_return;
1799286866Sjasone	}
1800286866Sjasone	ret = 0;
1801286866Sjasonelabel_return:
1802299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1803242844Sjasone	return (ret);
1804242844Sjasone}
1805242844Sjasone
1806242844Sjasonestatic const ctl_named_node_t *
1807299587Sjasonearena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1808242844Sjasone{
1809299587Sjasone	const ctl_named_node_t *ret;
1810242844Sjasone
1811299587Sjasone	malloc_mutex_lock(tsdn, &ctl_mtx);
1812242844Sjasone	if (i > ctl_stats.narenas) {
1813242844Sjasone		ret = NULL;
1814242844Sjasone		goto label_return;
1815242844Sjasone	}
1816242844Sjasone
1817242844Sjasone	ret = super_arena_i_node;
1818242844Sjasonelabel_return:
1819299587Sjasone	malloc_mutex_unlock(tsdn, &ctl_mtx);
1820242844Sjasone	return (ret);
1821242844Sjasone}
1822242844Sjasone
1823242844Sjasone/******************************************************************************/
1824242844Sjasone
1825242844Sjasonestatic int
1826299587Sjasonearenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1827242844Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1828242844Sjasone{
1829242844Sjasone	int ret;
1830242844Sjasone	unsigned narenas;
1831234370Sjasone
1832299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1833242844Sjasone	READONLY();
1834242844Sjasone	if (*oldlenp != sizeof(unsigned)) {
1835242844Sjasone		ret = EINVAL;
1836242844Sjasone		goto label_return;
1837242844Sjasone	}
1838242844Sjasone	narenas = ctl_stats.narenas;
1839242844Sjasone	READ(narenas, unsigned);
1840242844Sjasone
1841242844Sjasone	ret = 0;
1842242844Sjasonelabel_return:
1843299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1844242844Sjasone	return (ret);
1845242844Sjasone}
1846242844Sjasone
1847234370Sjasonestatic int
1848299587Sjasonearenas_initialized_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1849234370Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1850234370Sjasone{
1851234370Sjasone	int ret;
1852234370Sjasone	unsigned nread, i;
1853234370Sjasone
1854299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1855234370Sjasone	READONLY();
1856242844Sjasone	if (*oldlenp != ctl_stats.narenas * sizeof(bool)) {
1857234370Sjasone		ret = EINVAL;
1858242844Sjasone		nread = (*oldlenp < ctl_stats.narenas * sizeof(bool))
1859296221Sjasone		    ? (unsigned)(*oldlenp / sizeof(bool)) : ctl_stats.narenas;
1860234370Sjasone	} else {
1861234370Sjasone		ret = 0;
1862242844Sjasone		nread = ctl_stats.narenas;
1863234370Sjasone	}
1864234370Sjasone
1865234370Sjasone	for (i = 0; i < nread; i++)
1866234370Sjasone		((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
1867234370Sjasone
1868234370Sjasonelabel_return:
1869299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1870234370Sjasone	return (ret);
1871234370Sjasone}
1872234370Sjasone
1873286866Sjasonestatic int
1874299587Sjasonearenas_lg_dirty_mult_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1875299587Sjasone    void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1876286866Sjasone{
1877286866Sjasone	int ret;
1878286866Sjasone
1879286866Sjasone	if (oldp != NULL && oldlenp != NULL) {
1880286866Sjasone		size_t oldval = arena_lg_dirty_mult_default_get();
1881286866Sjasone		READ(oldval, ssize_t);
1882286866Sjasone	}
1883286866Sjasone	if (newp != NULL) {
1884286866Sjasone		if (newlen != sizeof(ssize_t)) {
1885286866Sjasone			ret = EINVAL;
1886286866Sjasone			goto label_return;
1887286866Sjasone		}
1888286866Sjasone		if (arena_lg_dirty_mult_default_set(*(ssize_t *)newp)) {
1889286866Sjasone			ret = EFAULT;
1890286866Sjasone			goto label_return;
1891286866Sjasone		}
1892286866Sjasone	}
1893286866Sjasone
1894286866Sjasone	ret = 0;
1895286866Sjasonelabel_return:
1896286866Sjasone	return (ret);
1897286866Sjasone}
1898286866Sjasone
1899296221Sjasonestatic int
1900299587Sjasonearenas_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1901296221Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1902296221Sjasone{
1903296221Sjasone	int ret;
1904296221Sjasone
1905296221Sjasone	if (oldp != NULL && oldlenp != NULL) {
1906296221Sjasone		size_t oldval = arena_decay_time_default_get();
1907296221Sjasone		READ(oldval, ssize_t);
1908296221Sjasone	}
1909296221Sjasone	if (newp != NULL) {
1910296221Sjasone		if (newlen != sizeof(ssize_t)) {
1911296221Sjasone			ret = EINVAL;
1912296221Sjasone			goto label_return;
1913296221Sjasone		}
1914296221Sjasone		if (arena_decay_time_default_set(*(ssize_t *)newp)) {
1915296221Sjasone			ret = EFAULT;
1916296221Sjasone			goto label_return;
1917296221Sjasone		}
1918296221Sjasone	}
1919296221Sjasone
1920296221Sjasone	ret = 0;
1921296221Sjasonelabel_return:
1922296221Sjasone	return (ret);
1923296221Sjasone}
1924296221Sjasone
1925234370SjasoneCTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
1926234370SjasoneCTL_RO_NL_GEN(arenas_page, PAGE, size_t)
1927234370SjasoneCTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)
1928234370SjasoneCTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)
1929234370SjasoneCTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)
1930261071SjasoneCTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)
1931261071SjasoneCTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)
1932261071SjasoneCTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)
1933261071Sjasonestatic const ctl_named_node_t *
1934299587Sjasonearenas_bin_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1935261071Sjasone{
1936261071Sjasone
1937261071Sjasone	if (i > NBINS)
1938261071Sjasone		return (NULL);
1939261071Sjasone	return (super_arenas_bin_i_node);
1940261071Sjasone}
1941261071Sjasone
1942286866SjasoneCTL_RO_NL_GEN(arenas_nlruns, nlclasses, unsigned)
1943296221SjasoneCTL_RO_NL_GEN(arenas_lrun_i_size, index2size(NBINS+(szind_t)mib[2]), size_t)
1944261071Sjasonestatic const ctl_named_node_t *
1945299587Sjasonearenas_lrun_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1946261071Sjasone{
1947234370Sjasone
1948261071Sjasone	if (i > nlclasses)
1949261071Sjasone		return (NULL);
1950261071Sjasone	return (super_arenas_lrun_i_node);
1951261071Sjasone}
1952261071Sjasone
1953286866SjasoneCTL_RO_NL_GEN(arenas_nhchunks, nhclasses, unsigned)
1954296221SjasoneCTL_RO_NL_GEN(arenas_hchunk_i_size, index2size(NBINS+nlclasses+(szind_t)mib[2]),
1955296221Sjasone    size_t)
1956286866Sjasonestatic const ctl_named_node_t *
1957299587Sjasonearenas_hchunk_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1958234370Sjasone{
1959234370Sjasone
1960286866Sjasone	if (i > nhclasses)
1961286866Sjasone		return (NULL);
1962286866Sjasone	return (super_arenas_hchunk_i_node);
1963242844Sjasone}
1964234370Sjasone
1965242844Sjasonestatic int
1966299587Sjasonearenas_extend_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1967299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1968242844Sjasone{
1969242844Sjasone	int ret;
1970245868Sjasone	unsigned narenas;
1971242844Sjasone
1972299587Sjasone	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1973242844Sjasone	READONLY();
1974299587Sjasone	if (ctl_grow(tsd_tsdn(tsd))) {
1975242844Sjasone		ret = EAGAIN;
1976242844Sjasone		goto label_return;
1977234370Sjasone	}
1978245868Sjasone	narenas = ctl_stats.narenas - 1;
1979245868Sjasone	READ(narenas, unsigned);
1980234370Sjasone
1981234370Sjasone	ret = 0;
1982234370Sjasonelabel_return:
1983299587Sjasone	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1984234370Sjasone	return (ret);
1985234370Sjasone}
1986234370Sjasone
1987234370Sjasone/******************************************************************************/
1988234370Sjasone
1989234370Sjasonestatic int
1990299587Sjasoneprof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1991299587Sjasone    void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1992286866Sjasone{
1993286866Sjasone	int ret;
1994286866Sjasone	bool oldval;
1995286866Sjasone
1996286866Sjasone	if (!config_prof)
1997286866Sjasone		return (ENOENT);
1998286866Sjasone
1999286866Sjasone	if (newp != NULL) {
2000286866Sjasone		if (newlen != sizeof(bool)) {
2001286866Sjasone			ret = EINVAL;
2002286866Sjasone			goto label_return;
2003286866Sjasone		}
2004299587Sjasone		oldval = prof_thread_active_init_set(tsd_tsdn(tsd),
2005299587Sjasone		    *(bool *)newp);
2006286866Sjasone	} else
2007299587Sjasone		oldval = prof_thread_active_init_get(tsd_tsdn(tsd));
2008286866Sjasone	READ(oldval, bool);
2009286866Sjasone
2010286866Sjasone	ret = 0;
2011286866Sjasonelabel_return:
2012286866Sjasone	return (ret);
2013286866Sjasone}
2014286866Sjasone
2015286866Sjasonestatic int
2016299587Sjasoneprof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2017299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
2018234370Sjasone{
2019234370Sjasone	int ret;
2020234370Sjasone	bool oldval;
2021234370Sjasone
2022286866Sjasone	if (!config_prof)
2023234370Sjasone		return (ENOENT);
2024234370Sjasone
2025234370Sjasone	if (newp != NULL) {
2026286866Sjasone		if (newlen != sizeof(bool)) {
2027286866Sjasone			ret = EINVAL;
2028286866Sjasone			goto label_return;
2029286866Sjasone		}
2030299587Sjasone		oldval = prof_active_set(tsd_tsdn(tsd), *(bool *)newp);
2031286866Sjasone	} else
2032299587Sjasone		oldval = prof_active_get(tsd_tsdn(tsd));
2033234370Sjasone	READ(oldval, bool);
2034234370Sjasone
2035234370Sjasone	ret = 0;
2036234370Sjasonelabel_return:
2037234370Sjasone	return (ret);
2038234370Sjasone}
2039234370Sjasone
2040234370Sjasonestatic int
2041299587Sjasoneprof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2042299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
2043234370Sjasone{
2044234370Sjasone	int ret;
2045234370Sjasone	const char *filename = NULL;
2046234370Sjasone
2047286866Sjasone	if (!config_prof)
2048234370Sjasone		return (ENOENT);
2049234370Sjasone
2050234370Sjasone	WRITEONLY();
2051234370Sjasone	WRITE(filename, const char *);
2052234370Sjasone
2053299587Sjasone	if (prof_mdump(tsd, filename)) {
2054234370Sjasone		ret = EFAULT;
2055234370Sjasone		goto label_return;
2056234370Sjasone	}
2057234370Sjasone
2058234370Sjasone	ret = 0;
2059234370Sjasonelabel_return:
2060234370Sjasone	return (ret);
2061234370Sjasone}
2062234370Sjasone
2063286866Sjasonestatic int
2064299587Sjasoneprof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2065299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
2066286866Sjasone{
2067286866Sjasone	int ret;
2068286866Sjasone	bool oldval;
2069286866Sjasone
2070286866Sjasone	if (!config_prof)
2071286866Sjasone		return (ENOENT);
2072286866Sjasone
2073286866Sjasone	if (newp != NULL) {
2074286866Sjasone		if (newlen != sizeof(bool)) {
2075286866Sjasone			ret = EINVAL;
2076286866Sjasone			goto label_return;
2077286866Sjasone		}
2078299587Sjasone		oldval = prof_gdump_set(tsd_tsdn(tsd), *(bool *)newp);
2079286866Sjasone	} else
2080299587Sjasone		oldval = prof_gdump_get(tsd_tsdn(tsd));
2081286866Sjasone	READ(oldval, bool);
2082286866Sjasone
2083286866Sjasone	ret = 0;
2084286866Sjasonelabel_return:
2085286866Sjasone	return (ret);
2086286866Sjasone}
2087286866Sjasone
2088286866Sjasonestatic int
2089299587Sjasoneprof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2090299587Sjasone    size_t *oldlenp, void *newp, size_t newlen)
2091286866Sjasone{
2092286866Sjasone	int ret;
2093286866Sjasone	size_t lg_sample = lg_prof_sample;
2094286866Sjasone
2095286866Sjasone	if (!config_prof)
2096286866Sjasone		return (ENOENT);
2097286866Sjasone
2098286866Sjasone	WRITEONLY();
2099286866Sjasone	WRITE(lg_sample, size_t);
2100286866Sjasone	if (lg_sample >= (sizeof(uint64_t) << 3))
2101286866Sjasone		lg_sample = (sizeof(uint64_t) << 3) - 1;
2102286866Sjasone
2103299587Sjasone	prof_reset(tsd_tsdn(tsd), lg_sample);
2104286866Sjasone
2105286866Sjasone	ret = 0;
2106286866Sjasonelabel_return:
2107286866Sjasone	return (ret);
2108286866Sjasone}
2109286866Sjasone
2110234370SjasoneCTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
2111286866SjasoneCTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t)
2112234370Sjasone
2113234370Sjasone/******************************************************************************/
2114234370Sjasone
2115261071SjasoneCTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)
2116261071SjasoneCTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)
2117261071SjasoneCTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
2118286866SjasoneCTL_RO_CGEN(config_stats, stats_metadata, ctl_stats.metadata, size_t)
2119286866SjasoneCTL_RO_CGEN(config_stats, stats_resident, ctl_stats.resident, size_t)
2120261071SjasoneCTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)
2121299587SjasoneCTL_RO_CGEN(config_stats, stats_retained, ctl_stats.retained, size_t)
2122261071Sjasone
2123261071SjasoneCTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)
2124286866SjasoneCTL_RO_GEN(stats_arenas_i_lg_dirty_mult, ctl_stats.arenas[mib[2]].lg_dirty_mult,
2125286866Sjasone    ssize_t)
2126296221SjasoneCTL_RO_GEN(stats_arenas_i_decay_time, ctl_stats.arenas[mib[2]].decay_time,
2127296221Sjasone    ssize_t)
2128261071SjasoneCTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)
2129261071SjasoneCTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
2130261071SjasoneCTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
2131261071SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
2132261071Sjasone    ctl_stats.arenas[mib[2]].astats.mapped, size_t)
2133299587SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_retained,
2134299587Sjasone    ctl_stats.arenas[mib[2]].astats.retained, size_t)
2135261071SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
2136261071Sjasone    ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
2137261071SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
2138261071Sjasone    ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)
2139261071SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_purged,
2140261071Sjasone    ctl_stats.arenas[mib[2]].astats.purged, uint64_t)
2141286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_metadata_mapped,
2142286866Sjasone    ctl_stats.arenas[mib[2]].astats.metadata_mapped, size_t)
2143286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_metadata_allocated,
2144286866Sjasone    ctl_stats.arenas[mib[2]].astats.metadata_allocated, size_t)
2145261071Sjasone
2146234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
2147234370Sjasone    ctl_stats.arenas[mib[2]].allocated_small, size_t)
2148234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
2149234370Sjasone    ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)
2150234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
2151234370Sjasone    ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)
2152234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
2153234370Sjasone    ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)
2154234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
2155234370Sjasone    ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)
2156234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
2157234370Sjasone    ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)
2158234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
2159234370Sjasone    ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)
2160234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
2161234370Sjasone    ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)
2162286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_huge_allocated,
2163286866Sjasone    ctl_stats.arenas[mib[2]].astats.allocated_huge, size_t)
2164286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_huge_nmalloc,
2165286866Sjasone    ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t)
2166286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_huge_ndalloc,
2167286866Sjasone    ctl_stats.arenas[mib[2]].astats.ndalloc_huge, uint64_t)
2168286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_huge_nrequests,
2169286866Sjasone    ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t) /* Intentional. */
2170234370Sjasone
2171234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
2172234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)
2173234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
2174234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)
2175234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
2176234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)
2177286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curregs,
2178286866Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].curregs, size_t)
2179234370SjasoneCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,
2180234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)
2181234370SjasoneCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,
2182234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)
2183234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,
2184234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)
2185234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,
2186234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)
2187234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,
2188234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)
2189234370Sjasone
2190242844Sjasonestatic const ctl_named_node_t *
2191299587Sjasonestats_arenas_i_bins_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
2192299587Sjasone    size_t j)
2193234370Sjasone{
2194234370Sjasone
2195234370Sjasone	if (j > NBINS)
2196234370Sjasone		return (NULL);
2197234370Sjasone	return (super_stats_arenas_i_bins_j_node);
2198234370Sjasone}
2199234370Sjasone
2200234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,
2201234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)
2202234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,
2203234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)
2204234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,
2205234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)
2206234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,
2207234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)
2208234370Sjasone
2209242844Sjasonestatic const ctl_named_node_t *
2210299587Sjasonestats_arenas_i_lruns_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
2211299587Sjasone    size_t j)
2212234370Sjasone{
2213234370Sjasone
2214234370Sjasone	if (j > nlclasses)
2215234370Sjasone		return (NULL);
2216234370Sjasone	return (super_stats_arenas_i_lruns_j_node);
2217234370Sjasone}
2218234370Sjasone
2219286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nmalloc,
2220286866Sjasone    ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, uint64_t)
2221286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_ndalloc,
2222286866Sjasone    ctl_stats.arenas[mib[2]].hstats[mib[4]].ndalloc, uint64_t)
2223286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nrequests,
2224286866Sjasone    ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, /* Intentional. */
2225286866Sjasone    uint64_t)
2226286866SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_curhchunks,
2227286866Sjasone    ctl_stats.arenas[mib[2]].hstats[mib[4]].curhchunks, size_t)
2228286866Sjasone
2229242844Sjasonestatic const ctl_named_node_t *
2230299587Sjasonestats_arenas_i_hchunks_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
2231299587Sjasone    size_t j)
2232286866Sjasone{
2233286866Sjasone
2234286866Sjasone	if (j > nhclasses)
2235286866Sjasone		return (NULL);
2236286866Sjasone	return (super_stats_arenas_i_hchunks_j_node);
2237286866Sjasone}
2238286866Sjasone
2239286866Sjasonestatic const ctl_named_node_t *
2240299587Sjasonestats_arenas_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
2241234370Sjasone{
2242235238Sjasone	const ctl_named_node_t * ret;
2243234370Sjasone
2244299587Sjasone	malloc_mutex_lock(tsdn, &ctl_mtx);
2245286866Sjasone	if (i > ctl_stats.narenas || !ctl_stats.arenas[i].initialized) {
2246234370Sjasone		ret = NULL;
2247234370Sjasone		goto label_return;
2248234370Sjasone	}
2249234370Sjasone
2250234370Sjasone	ret = super_stats_arenas_i_node;
2251234370Sjasonelabel_return:
2252299587Sjasone	malloc_mutex_unlock(tsdn, &ctl_mtx);
2253234370Sjasone	return (ret);
2254234370Sjasone}
2255