xref: /freebsd/contrib/jemalloc/src/ctl.c (revision bde951447fbed7c2669f80b5c7b6d3d16bb144f8)
1a4bd5210SJason Evans #define	JEMALLOC_CTL_C_
2a4bd5210SJason Evans #include "jemalloc/internal/jemalloc_internal.h"
3a4bd5210SJason Evans 
4a4bd5210SJason Evans /******************************************************************************/
5a4bd5210SJason Evans /* Data. */
6a4bd5210SJason Evans 
7a4bd5210SJason Evans /*
8a4bd5210SJason Evans  * ctl_mtx protects the following:
9a4bd5210SJason Evans  * - ctl_stats.*
10a4bd5210SJason Evans  */
11a4bd5210SJason Evans static malloc_mutex_t	ctl_mtx;
12a4bd5210SJason Evans static bool		ctl_initialized;
13a4bd5210SJason Evans static uint64_t		ctl_epoch;
14a4bd5210SJason Evans static ctl_stats_t	ctl_stats;
15a4bd5210SJason Evans 
16a4bd5210SJason Evans /******************************************************************************/
17e722f8f8SJason Evans /* Helpers for named and indexed nodes. */
18e722f8f8SJason Evans 
19d0e79aa3SJason Evans JEMALLOC_INLINE_C const ctl_named_node_t *
20e722f8f8SJason Evans ctl_named_node(const ctl_node_t *node)
21e722f8f8SJason Evans {
22e722f8f8SJason Evans 
23e722f8f8SJason Evans 	return ((node->named) ? (const ctl_named_node_t *)node : NULL);
24e722f8f8SJason Evans }
25e722f8f8SJason Evans 
26d0e79aa3SJason Evans JEMALLOC_INLINE_C const ctl_named_node_t *
27df0d881dSJason Evans ctl_named_children(const ctl_named_node_t *node, size_t index)
28e722f8f8SJason Evans {
29e722f8f8SJason Evans 	const ctl_named_node_t *children = ctl_named_node(node->children);
30e722f8f8SJason Evans 
31e722f8f8SJason Evans 	return (children ? &children[index] : NULL);
32e722f8f8SJason Evans }
33e722f8f8SJason Evans 
34d0e79aa3SJason Evans JEMALLOC_INLINE_C const ctl_indexed_node_t *
35e722f8f8SJason Evans ctl_indexed_node(const ctl_node_t *node)
36e722f8f8SJason Evans {
37e722f8f8SJason Evans 
38d0e79aa3SJason Evans 	return (!node->named ? (const ctl_indexed_node_t *)node : NULL);
39e722f8f8SJason Evans }
40e722f8f8SJason Evans 
41e722f8f8SJason Evans /******************************************************************************/
42a4bd5210SJason Evans /* Function prototypes for non-inline static functions. */
43a4bd5210SJason Evans 
44a4bd5210SJason Evans #define	CTL_PROTO(n)							\
451f0a49e8SJason Evans static int	n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,	\
461f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen);
47a4bd5210SJason Evans 
48a4bd5210SJason Evans #define	INDEX_PROTO(n)							\
491f0a49e8SJason Evans static const ctl_named_node_t	*n##_index(tsdn_t *tsdn,		\
501f0a49e8SJason Evans     const size_t *mib, size_t miblen, size_t i);
51a4bd5210SJason Evans 
52a4bd5210SJason Evans static bool	ctl_arena_init(ctl_arena_stats_t *astats);
53a4bd5210SJason Evans static void	ctl_arena_clear(ctl_arena_stats_t *astats);
541f0a49e8SJason Evans static void	ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_stats_t *cstats,
55a4bd5210SJason Evans     arena_t *arena);
56a4bd5210SJason Evans static void	ctl_arena_stats_smerge(ctl_arena_stats_t *sstats,
57a4bd5210SJason Evans     ctl_arena_stats_t *astats);
581f0a49e8SJason Evans static void	ctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, unsigned i);
591f0a49e8SJason Evans static bool	ctl_grow(tsdn_t *tsdn);
601f0a49e8SJason Evans static void	ctl_refresh(tsdn_t *tsdn);
611f0a49e8SJason Evans static bool	ctl_init(tsdn_t *tsdn);
621f0a49e8SJason Evans static int	ctl_lookup(tsdn_t *tsdn, const char *name,
631f0a49e8SJason Evans     ctl_node_t const **nodesp, size_t *mibp, size_t *depthp);
64a4bd5210SJason Evans 
65a4bd5210SJason Evans CTL_PROTO(version)
66a4bd5210SJason Evans CTL_PROTO(epoch)
67a4bd5210SJason Evans CTL_PROTO(thread_tcache_enabled)
68a4bd5210SJason Evans CTL_PROTO(thread_tcache_flush)
69d0e79aa3SJason Evans CTL_PROTO(thread_prof_name)
70d0e79aa3SJason Evans CTL_PROTO(thread_prof_active)
71a4bd5210SJason Evans CTL_PROTO(thread_arena)
72a4bd5210SJason Evans CTL_PROTO(thread_allocated)
73a4bd5210SJason Evans CTL_PROTO(thread_allocatedp)
74a4bd5210SJason Evans CTL_PROTO(thread_deallocated)
75a4bd5210SJason Evans CTL_PROTO(thread_deallocatedp)
76d0e79aa3SJason Evans CTL_PROTO(config_cache_oblivious)
77a4bd5210SJason Evans CTL_PROTO(config_debug)
78a4bd5210SJason Evans CTL_PROTO(config_fill)
79a4bd5210SJason Evans CTL_PROTO(config_lazy_lock)
80df0d881dSJason Evans CTL_PROTO(config_malloc_conf)
81a4bd5210SJason Evans CTL_PROTO(config_munmap)
82a4bd5210SJason Evans CTL_PROTO(config_prof)
83a4bd5210SJason Evans CTL_PROTO(config_prof_libgcc)
84a4bd5210SJason Evans CTL_PROTO(config_prof_libunwind)
85a4bd5210SJason Evans CTL_PROTO(config_stats)
86a4bd5210SJason Evans CTL_PROTO(config_tcache)
87a4bd5210SJason Evans CTL_PROTO(config_tls)
88a4bd5210SJason Evans CTL_PROTO(config_utrace)
89a4bd5210SJason Evans CTL_PROTO(config_valgrind)
90a4bd5210SJason Evans CTL_PROTO(config_xmalloc)
91a4bd5210SJason Evans CTL_PROTO(opt_abort)
9282872ac0SJason Evans CTL_PROTO(opt_dss)
93a4bd5210SJason Evans CTL_PROTO(opt_lg_chunk)
94a4bd5210SJason Evans CTL_PROTO(opt_narenas)
95df0d881dSJason Evans CTL_PROTO(opt_purge)
96a4bd5210SJason Evans CTL_PROTO(opt_lg_dirty_mult)
97df0d881dSJason Evans CTL_PROTO(opt_decay_time)
98a4bd5210SJason Evans CTL_PROTO(opt_stats_print)
99a4bd5210SJason Evans CTL_PROTO(opt_junk)
100a4bd5210SJason Evans CTL_PROTO(opt_zero)
101a4bd5210SJason Evans CTL_PROTO(opt_quarantine)
102a4bd5210SJason Evans CTL_PROTO(opt_redzone)
103a4bd5210SJason Evans CTL_PROTO(opt_utrace)
104a4bd5210SJason Evans CTL_PROTO(opt_xmalloc)
105a4bd5210SJason Evans CTL_PROTO(opt_tcache)
106a4bd5210SJason Evans CTL_PROTO(opt_lg_tcache_max)
107a4bd5210SJason Evans CTL_PROTO(opt_prof)
108a4bd5210SJason Evans CTL_PROTO(opt_prof_prefix)
109a4bd5210SJason Evans CTL_PROTO(opt_prof_active)
110d0e79aa3SJason Evans CTL_PROTO(opt_prof_thread_active_init)
111a4bd5210SJason Evans CTL_PROTO(opt_lg_prof_sample)
112a4bd5210SJason Evans CTL_PROTO(opt_lg_prof_interval)
113a4bd5210SJason Evans CTL_PROTO(opt_prof_gdump)
1148ed34ab0SJason Evans CTL_PROTO(opt_prof_final)
115a4bd5210SJason Evans CTL_PROTO(opt_prof_leak)
116a4bd5210SJason Evans CTL_PROTO(opt_prof_accum)
117d0e79aa3SJason Evans CTL_PROTO(tcache_create)
118d0e79aa3SJason Evans CTL_PROTO(tcache_flush)
119d0e79aa3SJason Evans CTL_PROTO(tcache_destroy)
1201f0a49e8SJason Evans static void	arena_i_purge(tsdn_t *tsdn, unsigned arena_ind, bool all);
12182872ac0SJason Evans CTL_PROTO(arena_i_purge)
122df0d881dSJason Evans CTL_PROTO(arena_i_decay)
1231f0a49e8SJason Evans CTL_PROTO(arena_i_reset)
12482872ac0SJason Evans CTL_PROTO(arena_i_dss)
125d0e79aa3SJason Evans CTL_PROTO(arena_i_lg_dirty_mult)
126df0d881dSJason Evans CTL_PROTO(arena_i_decay_time)
127d0e79aa3SJason Evans CTL_PROTO(arena_i_chunk_hooks)
12882872ac0SJason Evans INDEX_PROTO(arena_i)
129a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_size)
130a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_nregs)
131a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_run_size)
132a4bd5210SJason Evans INDEX_PROTO(arenas_bin_i)
133a4bd5210SJason Evans CTL_PROTO(arenas_lrun_i_size)
134a4bd5210SJason Evans INDEX_PROTO(arenas_lrun_i)
135d0e79aa3SJason Evans CTL_PROTO(arenas_hchunk_i_size)
136d0e79aa3SJason Evans INDEX_PROTO(arenas_hchunk_i)
137a4bd5210SJason Evans CTL_PROTO(arenas_narenas)
138a4bd5210SJason Evans CTL_PROTO(arenas_initialized)
139d0e79aa3SJason Evans CTL_PROTO(arenas_lg_dirty_mult)
140df0d881dSJason Evans CTL_PROTO(arenas_decay_time)
141a4bd5210SJason Evans CTL_PROTO(arenas_quantum)
142a4bd5210SJason Evans CTL_PROTO(arenas_page)
143a4bd5210SJason Evans CTL_PROTO(arenas_tcache_max)
144a4bd5210SJason Evans CTL_PROTO(arenas_nbins)
145a4bd5210SJason Evans CTL_PROTO(arenas_nhbins)
146a4bd5210SJason Evans CTL_PROTO(arenas_nlruns)
147d0e79aa3SJason Evans CTL_PROTO(arenas_nhchunks)
14882872ac0SJason Evans CTL_PROTO(arenas_extend)
149d0e79aa3SJason Evans CTL_PROTO(prof_thread_active_init)
150a4bd5210SJason Evans CTL_PROTO(prof_active)
151a4bd5210SJason Evans CTL_PROTO(prof_dump)
152d0e79aa3SJason Evans CTL_PROTO(prof_gdump)
153d0e79aa3SJason Evans CTL_PROTO(prof_reset)
154a4bd5210SJason Evans CTL_PROTO(prof_interval)
155d0e79aa3SJason Evans CTL_PROTO(lg_prof_sample)
156a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_allocated)
157a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_nmalloc)
158a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_ndalloc)
159a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_nrequests)
160a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_allocated)
161a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_nmalloc)
162a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_ndalloc)
163a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_nrequests)
164d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_huge_allocated)
165d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_huge_nmalloc)
166d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_huge_ndalloc)
167d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_huge_nrequests)
168a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nmalloc)
169a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_ndalloc)
170a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nrequests)
171d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_bins_j_curregs)
172a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nfills)
173a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nflushes)
174a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nruns)
175a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nreruns)
176a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_curruns)
177a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i_bins_j)
178a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_nmalloc)
179a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_ndalloc)
180a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_nrequests)
181a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_curruns)
182a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i_lruns_j)
183d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_hchunks_j_nmalloc)
184d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_hchunks_j_ndalloc)
185d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_hchunks_j_nrequests)
186d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_hchunks_j_curhchunks)
187d0e79aa3SJason Evans INDEX_PROTO(stats_arenas_i_hchunks_j)
188a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_nthreads)
18982872ac0SJason Evans CTL_PROTO(stats_arenas_i_dss)
190d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_lg_dirty_mult)
191df0d881dSJason Evans CTL_PROTO(stats_arenas_i_decay_time)
192a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_pactive)
193a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_pdirty)
194a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_mapped)
1951f0a49e8SJason Evans CTL_PROTO(stats_arenas_i_retained)
196a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_npurge)
197a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_nmadvise)
198a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_purged)
199d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_metadata_mapped)
200d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_metadata_allocated)
201a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i)
202a4bd5210SJason Evans CTL_PROTO(stats_cactive)
203a4bd5210SJason Evans CTL_PROTO(stats_allocated)
204a4bd5210SJason Evans CTL_PROTO(stats_active)
205d0e79aa3SJason Evans CTL_PROTO(stats_metadata)
206d0e79aa3SJason Evans CTL_PROTO(stats_resident)
207a4bd5210SJason Evans CTL_PROTO(stats_mapped)
2081f0a49e8SJason Evans CTL_PROTO(stats_retained)
209a4bd5210SJason Evans 
210a4bd5210SJason Evans /******************************************************************************/
211a4bd5210SJason Evans /* mallctl tree. */
212a4bd5210SJason Evans 
213a4bd5210SJason Evans /* Maximum tree depth. */
214a4bd5210SJason Evans #define	CTL_MAX_DEPTH	6
215a4bd5210SJason Evans 
216e722f8f8SJason Evans #define	NAME(n)	{true},	n
217e722f8f8SJason Evans #define	CHILD(t, c)							\
218e722f8f8SJason Evans 	sizeof(c##_node) / sizeof(ctl_##t##_node_t),			\
219e722f8f8SJason Evans 	(ctl_node_t *)c##_node,						\
220e722f8f8SJason Evans 	NULL
221e722f8f8SJason Evans #define	CTL(c)	0, NULL, c##_ctl
222a4bd5210SJason Evans 
223a4bd5210SJason Evans /*
224a4bd5210SJason Evans  * Only handles internal indexed nodes, since there are currently no external
225a4bd5210SJason Evans  * ones.
226a4bd5210SJason Evans  */
227e722f8f8SJason Evans #define	INDEX(i)	{false},	i##_index
228a4bd5210SJason Evans 
229d0e79aa3SJason Evans static const ctl_named_node_t	thread_tcache_node[] = {
230a4bd5210SJason Evans 	{NAME("enabled"),	CTL(thread_tcache_enabled)},
231a4bd5210SJason Evans 	{NAME("flush"),		CTL(thread_tcache_flush)}
232a4bd5210SJason Evans };
233a4bd5210SJason Evans 
234d0e79aa3SJason Evans static const ctl_named_node_t	thread_prof_node[] = {
235d0e79aa3SJason Evans 	{NAME("name"),		CTL(thread_prof_name)},
236d0e79aa3SJason Evans 	{NAME("active"),	CTL(thread_prof_active)}
237d0e79aa3SJason Evans };
238d0e79aa3SJason Evans 
239e722f8f8SJason Evans static const ctl_named_node_t	thread_node[] = {
240a4bd5210SJason Evans 	{NAME("arena"),		CTL(thread_arena)},
241a4bd5210SJason Evans 	{NAME("allocated"),	CTL(thread_allocated)},
242a4bd5210SJason Evans 	{NAME("allocatedp"),	CTL(thread_allocatedp)},
243a4bd5210SJason Evans 	{NAME("deallocated"),	CTL(thread_deallocated)},
244a4bd5210SJason Evans 	{NAME("deallocatedp"),	CTL(thread_deallocatedp)},
245d0e79aa3SJason Evans 	{NAME("tcache"),	CHILD(named, thread_tcache)},
246d0e79aa3SJason Evans 	{NAME("prof"),		CHILD(named, thread_prof)}
247a4bd5210SJason Evans };
248a4bd5210SJason Evans 
249e722f8f8SJason Evans static const ctl_named_node_t	config_node[] = {
250d0e79aa3SJason Evans 	{NAME("cache_oblivious"), CTL(config_cache_oblivious)},
251a4bd5210SJason Evans 	{NAME("debug"),		CTL(config_debug)},
252a4bd5210SJason Evans 	{NAME("fill"),		CTL(config_fill)},
253a4bd5210SJason Evans 	{NAME("lazy_lock"),	CTL(config_lazy_lock)},
254df0d881dSJason Evans 	{NAME("malloc_conf"),	CTL(config_malloc_conf)},
255a4bd5210SJason Evans 	{NAME("munmap"),	CTL(config_munmap)},
256a4bd5210SJason Evans 	{NAME("prof"),		CTL(config_prof)},
257a4bd5210SJason Evans 	{NAME("prof_libgcc"),	CTL(config_prof_libgcc)},
258a4bd5210SJason Evans 	{NAME("prof_libunwind"), CTL(config_prof_libunwind)},
259a4bd5210SJason Evans 	{NAME("stats"),		CTL(config_stats)},
260a4bd5210SJason Evans 	{NAME("tcache"),	CTL(config_tcache)},
261a4bd5210SJason Evans 	{NAME("tls"),		CTL(config_tls)},
262a4bd5210SJason Evans 	{NAME("utrace"),	CTL(config_utrace)},
263a4bd5210SJason Evans 	{NAME("valgrind"),	CTL(config_valgrind)},
264a4bd5210SJason Evans 	{NAME("xmalloc"),	CTL(config_xmalloc)}
265a4bd5210SJason Evans };
266a4bd5210SJason Evans 
267e722f8f8SJason Evans static const ctl_named_node_t opt_node[] = {
268a4bd5210SJason Evans 	{NAME("abort"),		CTL(opt_abort)},
26982872ac0SJason Evans 	{NAME("dss"),		CTL(opt_dss)},
270a4bd5210SJason Evans 	{NAME("lg_chunk"),	CTL(opt_lg_chunk)},
271a4bd5210SJason Evans 	{NAME("narenas"),	CTL(opt_narenas)},
272df0d881dSJason Evans 	{NAME("purge"),		CTL(opt_purge)},
273a4bd5210SJason Evans 	{NAME("lg_dirty_mult"),	CTL(opt_lg_dirty_mult)},
274df0d881dSJason Evans 	{NAME("decay_time"),	CTL(opt_decay_time)},
275a4bd5210SJason Evans 	{NAME("stats_print"),	CTL(opt_stats_print)},
276a4bd5210SJason Evans 	{NAME("junk"),		CTL(opt_junk)},
277a4bd5210SJason Evans 	{NAME("zero"),		CTL(opt_zero)},
278a4bd5210SJason Evans 	{NAME("quarantine"),	CTL(opt_quarantine)},
279a4bd5210SJason Evans 	{NAME("redzone"),	CTL(opt_redzone)},
280a4bd5210SJason Evans 	{NAME("utrace"),	CTL(opt_utrace)},
281a4bd5210SJason Evans 	{NAME("xmalloc"),	CTL(opt_xmalloc)},
282a4bd5210SJason Evans 	{NAME("tcache"),	CTL(opt_tcache)},
283a4bd5210SJason Evans 	{NAME("lg_tcache_max"),	CTL(opt_lg_tcache_max)},
284a4bd5210SJason Evans 	{NAME("prof"),		CTL(opt_prof)},
285a4bd5210SJason Evans 	{NAME("prof_prefix"),	CTL(opt_prof_prefix)},
286a4bd5210SJason Evans 	{NAME("prof_active"),	CTL(opt_prof_active)},
287d0e79aa3SJason Evans 	{NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)},
288a4bd5210SJason Evans 	{NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
289a4bd5210SJason Evans 	{NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
290a4bd5210SJason Evans 	{NAME("prof_gdump"),	CTL(opt_prof_gdump)},
2918ed34ab0SJason Evans 	{NAME("prof_final"),	CTL(opt_prof_final)},
292a4bd5210SJason Evans 	{NAME("prof_leak"),	CTL(opt_prof_leak)},
293a4bd5210SJason Evans 	{NAME("prof_accum"),	CTL(opt_prof_accum)}
294a4bd5210SJason Evans };
295a4bd5210SJason Evans 
296d0e79aa3SJason Evans static const ctl_named_node_t	tcache_node[] = {
297d0e79aa3SJason Evans 	{NAME("create"),	CTL(tcache_create)},
298d0e79aa3SJason Evans 	{NAME("flush"),		CTL(tcache_flush)},
299d0e79aa3SJason Evans 	{NAME("destroy"),	CTL(tcache_destroy)}
300d0e79aa3SJason Evans };
301d0e79aa3SJason Evans 
30282872ac0SJason Evans static const ctl_named_node_t arena_i_node[] = {
30382872ac0SJason Evans 	{NAME("purge"),		CTL(arena_i_purge)},
304df0d881dSJason Evans 	{NAME("decay"),		CTL(arena_i_decay)},
3051f0a49e8SJason Evans 	{NAME("reset"),		CTL(arena_i_reset)},
306d0e79aa3SJason Evans 	{NAME("dss"),		CTL(arena_i_dss)},
307d0e79aa3SJason Evans 	{NAME("lg_dirty_mult"),	CTL(arena_i_lg_dirty_mult)},
308df0d881dSJason Evans 	{NAME("decay_time"),	CTL(arena_i_decay_time)},
309d0e79aa3SJason Evans 	{NAME("chunk_hooks"),	CTL(arena_i_chunk_hooks)}
31082872ac0SJason Evans };
31182872ac0SJason Evans static const ctl_named_node_t super_arena_i_node[] = {
31282872ac0SJason Evans 	{NAME(""),		CHILD(named, arena_i)}
31382872ac0SJason Evans };
31482872ac0SJason Evans 
31582872ac0SJason Evans static const ctl_indexed_node_t arena_node[] = {
31682872ac0SJason Evans 	{INDEX(arena_i)}
31782872ac0SJason Evans };
31882872ac0SJason Evans 
319e722f8f8SJason Evans static const ctl_named_node_t arenas_bin_i_node[] = {
320a4bd5210SJason Evans 	{NAME("size"),		CTL(arenas_bin_i_size)},
321a4bd5210SJason Evans 	{NAME("nregs"),		CTL(arenas_bin_i_nregs)},
322a4bd5210SJason Evans 	{NAME("run_size"),	CTL(arenas_bin_i_run_size)}
323a4bd5210SJason Evans };
324e722f8f8SJason Evans static const ctl_named_node_t super_arenas_bin_i_node[] = {
325e722f8f8SJason Evans 	{NAME(""),		CHILD(named, arenas_bin_i)}
326a4bd5210SJason Evans };
327a4bd5210SJason Evans 
328e722f8f8SJason Evans static const ctl_indexed_node_t arenas_bin_node[] = {
329a4bd5210SJason Evans 	{INDEX(arenas_bin_i)}
330a4bd5210SJason Evans };
331a4bd5210SJason Evans 
332e722f8f8SJason Evans static const ctl_named_node_t arenas_lrun_i_node[] = {
333a4bd5210SJason Evans 	{NAME("size"),		CTL(arenas_lrun_i_size)}
334a4bd5210SJason Evans };
335e722f8f8SJason Evans static const ctl_named_node_t super_arenas_lrun_i_node[] = {
336e722f8f8SJason Evans 	{NAME(""),		CHILD(named, arenas_lrun_i)}
337a4bd5210SJason Evans };
338a4bd5210SJason Evans 
339e722f8f8SJason Evans static const ctl_indexed_node_t arenas_lrun_node[] = {
340a4bd5210SJason Evans 	{INDEX(arenas_lrun_i)}
341a4bd5210SJason Evans };
342a4bd5210SJason Evans 
343d0e79aa3SJason Evans static const ctl_named_node_t arenas_hchunk_i_node[] = {
344d0e79aa3SJason Evans 	{NAME("size"),		CTL(arenas_hchunk_i_size)}
345d0e79aa3SJason Evans };
346d0e79aa3SJason Evans static const ctl_named_node_t super_arenas_hchunk_i_node[] = {
347d0e79aa3SJason Evans 	{NAME(""),		CHILD(named, arenas_hchunk_i)}
348d0e79aa3SJason Evans };
349d0e79aa3SJason Evans 
350d0e79aa3SJason Evans static const ctl_indexed_node_t arenas_hchunk_node[] = {
351d0e79aa3SJason Evans 	{INDEX(arenas_hchunk_i)}
352d0e79aa3SJason Evans };
353d0e79aa3SJason Evans 
354e722f8f8SJason Evans static const ctl_named_node_t arenas_node[] = {
355a4bd5210SJason Evans 	{NAME("narenas"),	CTL(arenas_narenas)},
356a4bd5210SJason Evans 	{NAME("initialized"),	CTL(arenas_initialized)},
357d0e79aa3SJason Evans 	{NAME("lg_dirty_mult"),	CTL(arenas_lg_dirty_mult)},
358df0d881dSJason Evans 	{NAME("decay_time"),	CTL(arenas_decay_time)},
359a4bd5210SJason Evans 	{NAME("quantum"),	CTL(arenas_quantum)},
360a4bd5210SJason Evans 	{NAME("page"),		CTL(arenas_page)},
361a4bd5210SJason Evans 	{NAME("tcache_max"),	CTL(arenas_tcache_max)},
362a4bd5210SJason Evans 	{NAME("nbins"),		CTL(arenas_nbins)},
363a4bd5210SJason Evans 	{NAME("nhbins"),	CTL(arenas_nhbins)},
364e722f8f8SJason Evans 	{NAME("bin"),		CHILD(indexed, arenas_bin)},
365a4bd5210SJason Evans 	{NAME("nlruns"),	CTL(arenas_nlruns)},
366e722f8f8SJason Evans 	{NAME("lrun"),		CHILD(indexed, arenas_lrun)},
367d0e79aa3SJason Evans 	{NAME("nhchunks"),	CTL(arenas_nhchunks)},
368d0e79aa3SJason Evans 	{NAME("hchunk"),	CHILD(indexed, arenas_hchunk)},
36982872ac0SJason Evans 	{NAME("extend"),	CTL(arenas_extend)}
370a4bd5210SJason Evans };
371a4bd5210SJason Evans 
372e722f8f8SJason Evans static const ctl_named_node_t	prof_node[] = {
373d0e79aa3SJason Evans 	{NAME("thread_active_init"), CTL(prof_thread_active_init)},
374a4bd5210SJason Evans 	{NAME("active"),	CTL(prof_active)},
375a4bd5210SJason Evans 	{NAME("dump"),		CTL(prof_dump)},
376d0e79aa3SJason Evans 	{NAME("gdump"),		CTL(prof_gdump)},
377d0e79aa3SJason Evans 	{NAME("reset"),		CTL(prof_reset)},
378d0e79aa3SJason Evans 	{NAME("interval"),	CTL(prof_interval)},
379d0e79aa3SJason Evans 	{NAME("lg_sample"),	CTL(lg_prof_sample)}
380a4bd5210SJason Evans };
381a4bd5210SJason Evans 
382d0e79aa3SJason Evans static const ctl_named_node_t stats_arenas_i_metadata_node[] = {
383d0e79aa3SJason Evans 	{NAME("mapped"),	CTL(stats_arenas_i_metadata_mapped)},
384d0e79aa3SJason Evans 	{NAME("allocated"),	CTL(stats_arenas_i_metadata_allocated)}
385a4bd5210SJason Evans };
386a4bd5210SJason Evans 
387e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_small_node[] = {
388a4bd5210SJason Evans 	{NAME("allocated"),	CTL(stats_arenas_i_small_allocated)},
389a4bd5210SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_small_nmalloc)},
390a4bd5210SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_small_ndalloc)},
391a4bd5210SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_small_nrequests)}
392a4bd5210SJason Evans };
393a4bd5210SJason Evans 
394e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_large_node[] = {
395a4bd5210SJason Evans 	{NAME("allocated"),	CTL(stats_arenas_i_large_allocated)},
396a4bd5210SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_large_nmalloc)},
397a4bd5210SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_large_ndalloc)},
398a4bd5210SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_large_nrequests)}
399a4bd5210SJason Evans };
400a4bd5210SJason Evans 
401d0e79aa3SJason Evans static const ctl_named_node_t stats_arenas_i_huge_node[] = {
402d0e79aa3SJason Evans 	{NAME("allocated"),	CTL(stats_arenas_i_huge_allocated)},
403d0e79aa3SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_huge_nmalloc)},
404d0e79aa3SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_huge_ndalloc)},
405d0e79aa3SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_huge_nrequests)}
406d0e79aa3SJason Evans };
407d0e79aa3SJason Evans 
408e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_bins_j_node[] = {
409a4bd5210SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_bins_j_nmalloc)},
410a4bd5210SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_bins_j_ndalloc)},
411a4bd5210SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_bins_j_nrequests)},
412d0e79aa3SJason Evans 	{NAME("curregs"),	CTL(stats_arenas_i_bins_j_curregs)},
413a4bd5210SJason Evans 	{NAME("nfills"),	CTL(stats_arenas_i_bins_j_nfills)},
414a4bd5210SJason Evans 	{NAME("nflushes"),	CTL(stats_arenas_i_bins_j_nflushes)},
415a4bd5210SJason Evans 	{NAME("nruns"),		CTL(stats_arenas_i_bins_j_nruns)},
416a4bd5210SJason Evans 	{NAME("nreruns"),	CTL(stats_arenas_i_bins_j_nreruns)},
417a4bd5210SJason Evans 	{NAME("curruns"),	CTL(stats_arenas_i_bins_j_curruns)}
418a4bd5210SJason Evans };
419e722f8f8SJason Evans static const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {
420e722f8f8SJason Evans 	{NAME(""),		CHILD(named, stats_arenas_i_bins_j)}
421a4bd5210SJason Evans };
422a4bd5210SJason Evans 
423e722f8f8SJason Evans static const ctl_indexed_node_t stats_arenas_i_bins_node[] = {
424a4bd5210SJason Evans 	{INDEX(stats_arenas_i_bins_j)}
425a4bd5210SJason Evans };
426a4bd5210SJason Evans 
427e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {
428a4bd5210SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_lruns_j_nmalloc)},
429a4bd5210SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_lruns_j_ndalloc)},
430a4bd5210SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_lruns_j_nrequests)},
431a4bd5210SJason Evans 	{NAME("curruns"),	CTL(stats_arenas_i_lruns_j_curruns)}
432a4bd5210SJason Evans };
433e722f8f8SJason Evans static const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {
434e722f8f8SJason Evans 	{NAME(""),		CHILD(named, stats_arenas_i_lruns_j)}
435a4bd5210SJason Evans };
436a4bd5210SJason Evans 
437e722f8f8SJason Evans static const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {
438a4bd5210SJason Evans 	{INDEX(stats_arenas_i_lruns_j)}
439a4bd5210SJason Evans };
440a4bd5210SJason Evans 
441d0e79aa3SJason Evans static const ctl_named_node_t stats_arenas_i_hchunks_j_node[] = {
442d0e79aa3SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_hchunks_j_nmalloc)},
443d0e79aa3SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_hchunks_j_ndalloc)},
444d0e79aa3SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_hchunks_j_nrequests)},
445d0e79aa3SJason Evans 	{NAME("curhchunks"),	CTL(stats_arenas_i_hchunks_j_curhchunks)}
446d0e79aa3SJason Evans };
447d0e79aa3SJason Evans static const ctl_named_node_t super_stats_arenas_i_hchunks_j_node[] = {
448d0e79aa3SJason Evans 	{NAME(""),		CHILD(named, stats_arenas_i_hchunks_j)}
449d0e79aa3SJason Evans };
450d0e79aa3SJason Evans 
451d0e79aa3SJason Evans static const ctl_indexed_node_t stats_arenas_i_hchunks_node[] = {
452d0e79aa3SJason Evans 	{INDEX(stats_arenas_i_hchunks_j)}
453d0e79aa3SJason Evans };
454d0e79aa3SJason Evans 
455e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_node[] = {
456a4bd5210SJason Evans 	{NAME("nthreads"),	CTL(stats_arenas_i_nthreads)},
45782872ac0SJason Evans 	{NAME("dss"),		CTL(stats_arenas_i_dss)},
458d0e79aa3SJason Evans 	{NAME("lg_dirty_mult"),	CTL(stats_arenas_i_lg_dirty_mult)},
459df0d881dSJason Evans 	{NAME("decay_time"),	CTL(stats_arenas_i_decay_time)},
460a4bd5210SJason Evans 	{NAME("pactive"),	CTL(stats_arenas_i_pactive)},
461a4bd5210SJason Evans 	{NAME("pdirty"),	CTL(stats_arenas_i_pdirty)},
462a4bd5210SJason Evans 	{NAME("mapped"),	CTL(stats_arenas_i_mapped)},
4631f0a49e8SJason Evans 	{NAME("retained"),	CTL(stats_arenas_i_retained)},
464a4bd5210SJason Evans 	{NAME("npurge"),	CTL(stats_arenas_i_npurge)},
465a4bd5210SJason Evans 	{NAME("nmadvise"),	CTL(stats_arenas_i_nmadvise)},
466a4bd5210SJason Evans 	{NAME("purged"),	CTL(stats_arenas_i_purged)},
467d0e79aa3SJason Evans 	{NAME("metadata"),	CHILD(named, stats_arenas_i_metadata)},
468e722f8f8SJason Evans 	{NAME("small"),		CHILD(named, stats_arenas_i_small)},
469e722f8f8SJason Evans 	{NAME("large"),		CHILD(named, stats_arenas_i_large)},
470d0e79aa3SJason Evans 	{NAME("huge"),		CHILD(named, stats_arenas_i_huge)},
471e722f8f8SJason Evans 	{NAME("bins"),		CHILD(indexed, stats_arenas_i_bins)},
472d0e79aa3SJason Evans 	{NAME("lruns"),		CHILD(indexed, stats_arenas_i_lruns)},
473d0e79aa3SJason Evans 	{NAME("hchunks"),	CHILD(indexed, stats_arenas_i_hchunks)}
474a4bd5210SJason Evans };
475e722f8f8SJason Evans static const ctl_named_node_t super_stats_arenas_i_node[] = {
476e722f8f8SJason Evans 	{NAME(""),		CHILD(named, stats_arenas_i)}
477a4bd5210SJason Evans };
478a4bd5210SJason Evans 
479e722f8f8SJason Evans static const ctl_indexed_node_t stats_arenas_node[] = {
480a4bd5210SJason Evans 	{INDEX(stats_arenas_i)}
481a4bd5210SJason Evans };
482a4bd5210SJason Evans 
483e722f8f8SJason Evans static const ctl_named_node_t stats_node[] = {
484a4bd5210SJason Evans 	{NAME("cactive"),	CTL(stats_cactive)},
485a4bd5210SJason Evans 	{NAME("allocated"),	CTL(stats_allocated)},
486a4bd5210SJason Evans 	{NAME("active"),	CTL(stats_active)},
487d0e79aa3SJason Evans 	{NAME("metadata"),	CTL(stats_metadata)},
488d0e79aa3SJason Evans 	{NAME("resident"),	CTL(stats_resident)},
489a4bd5210SJason Evans 	{NAME("mapped"),	CTL(stats_mapped)},
4901f0a49e8SJason Evans 	{NAME("retained"),	CTL(stats_retained)},
491e722f8f8SJason Evans 	{NAME("arenas"),	CHILD(indexed, stats_arenas)}
492a4bd5210SJason Evans };
493a4bd5210SJason Evans 
494e722f8f8SJason Evans static const ctl_named_node_t	root_node[] = {
495a4bd5210SJason Evans 	{NAME("version"),	CTL(version)},
496a4bd5210SJason Evans 	{NAME("epoch"),		CTL(epoch)},
497e722f8f8SJason Evans 	{NAME("thread"),	CHILD(named, thread)},
498e722f8f8SJason Evans 	{NAME("config"),	CHILD(named, config)},
499e722f8f8SJason Evans 	{NAME("opt"),		CHILD(named, opt)},
500d0e79aa3SJason Evans 	{NAME("tcache"),	CHILD(named, tcache)},
50182872ac0SJason Evans 	{NAME("arena"),		CHILD(indexed, arena)},
502e722f8f8SJason Evans 	{NAME("arenas"),	CHILD(named, arenas)},
503e722f8f8SJason Evans 	{NAME("prof"),		CHILD(named, prof)},
504e722f8f8SJason Evans 	{NAME("stats"),		CHILD(named, stats)}
505a4bd5210SJason Evans };
506e722f8f8SJason Evans static const ctl_named_node_t super_root_node[] = {
507e722f8f8SJason Evans 	{NAME(""),		CHILD(named, root)}
508a4bd5210SJason Evans };
509a4bd5210SJason Evans 
510a4bd5210SJason Evans #undef NAME
511a4bd5210SJason Evans #undef CHILD
512a4bd5210SJason Evans #undef CTL
513a4bd5210SJason Evans #undef INDEX
514a4bd5210SJason Evans 
515a4bd5210SJason Evans /******************************************************************************/
516a4bd5210SJason Evans 
517a4bd5210SJason Evans static bool
518a4bd5210SJason Evans ctl_arena_init(ctl_arena_stats_t *astats)
519a4bd5210SJason Evans {
520a4bd5210SJason Evans 
521a4bd5210SJason Evans 	if (astats->lstats == NULL) {
522d0e79aa3SJason Evans 		astats->lstats = (malloc_large_stats_t *)a0malloc(nlclasses *
523a4bd5210SJason Evans 		    sizeof(malloc_large_stats_t));
524a4bd5210SJason Evans 		if (astats->lstats == NULL)
525a4bd5210SJason Evans 			return (true);
526a4bd5210SJason Evans 	}
527a4bd5210SJason Evans 
528d0e79aa3SJason Evans 	if (astats->hstats == NULL) {
529d0e79aa3SJason Evans 		astats->hstats = (malloc_huge_stats_t *)a0malloc(nhclasses *
530d0e79aa3SJason Evans 		    sizeof(malloc_huge_stats_t));
531d0e79aa3SJason Evans 		if (astats->hstats == NULL)
532d0e79aa3SJason Evans 			return (true);
533d0e79aa3SJason Evans 	}
534d0e79aa3SJason Evans 
535a4bd5210SJason Evans 	return (false);
536a4bd5210SJason Evans }
537a4bd5210SJason Evans 
538a4bd5210SJason Evans static void
539a4bd5210SJason Evans ctl_arena_clear(ctl_arena_stats_t *astats)
540a4bd5210SJason Evans {
541a4bd5210SJason Evans 
542df0d881dSJason Evans 	astats->nthreads = 0;
54382872ac0SJason Evans 	astats->dss = dss_prec_names[dss_prec_limit];
544d0e79aa3SJason Evans 	astats->lg_dirty_mult = -1;
545df0d881dSJason Evans 	astats->decay_time = -1;
546a4bd5210SJason Evans 	astats->pactive = 0;
547a4bd5210SJason Evans 	astats->pdirty = 0;
548a4bd5210SJason Evans 	if (config_stats) {
549a4bd5210SJason Evans 		memset(&astats->astats, 0, sizeof(arena_stats_t));
550a4bd5210SJason Evans 		astats->allocated_small = 0;
551a4bd5210SJason Evans 		astats->nmalloc_small = 0;
552a4bd5210SJason Evans 		astats->ndalloc_small = 0;
553a4bd5210SJason Evans 		astats->nrequests_small = 0;
554a4bd5210SJason Evans 		memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));
555a4bd5210SJason Evans 		memset(astats->lstats, 0, nlclasses *
556a4bd5210SJason Evans 		    sizeof(malloc_large_stats_t));
557d0e79aa3SJason Evans 		memset(astats->hstats, 0, nhclasses *
558d0e79aa3SJason Evans 		    sizeof(malloc_huge_stats_t));
559a4bd5210SJason Evans 	}
560a4bd5210SJason Evans }
561a4bd5210SJason Evans 
562a4bd5210SJason Evans static void
5631f0a49e8SJason Evans ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_stats_t *cstats, arena_t *arena)
564a4bd5210SJason Evans {
565a4bd5210SJason Evans 	unsigned i;
566a4bd5210SJason Evans 
567df0d881dSJason Evans 	if (config_stats) {
5681f0a49e8SJason Evans 		arena_stats_merge(tsdn, arena, &cstats->nthreads, &cstats->dss,
569df0d881dSJason Evans 		    &cstats->lg_dirty_mult, &cstats->decay_time,
570df0d881dSJason Evans 		    &cstats->pactive, &cstats->pdirty, &cstats->astats,
571df0d881dSJason Evans 		    cstats->bstats, cstats->lstats, cstats->hstats);
572a4bd5210SJason Evans 
573a4bd5210SJason Evans 		for (i = 0; i < NBINS; i++) {
574d0e79aa3SJason Evans 			cstats->allocated_small += cstats->bstats[i].curregs *
575d0e79aa3SJason Evans 			    index2size(i);
576a4bd5210SJason Evans 			cstats->nmalloc_small += cstats->bstats[i].nmalloc;
577a4bd5210SJason Evans 			cstats->ndalloc_small += cstats->bstats[i].ndalloc;
578a4bd5210SJason Evans 			cstats->nrequests_small += cstats->bstats[i].nrequests;
579a4bd5210SJason Evans 		}
580df0d881dSJason Evans 	} else {
5811f0a49e8SJason Evans 		arena_basic_stats_merge(tsdn, arena, &cstats->nthreads,
5821f0a49e8SJason Evans 		    &cstats->dss, &cstats->lg_dirty_mult, &cstats->decay_time,
583df0d881dSJason Evans 		    &cstats->pactive, &cstats->pdirty);
584df0d881dSJason Evans 	}
585a4bd5210SJason Evans }
586a4bd5210SJason Evans 
587a4bd5210SJason Evans static void
588a4bd5210SJason Evans ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)
589a4bd5210SJason Evans {
590a4bd5210SJason Evans 	unsigned i;
591a4bd5210SJason Evans 
592df0d881dSJason Evans 	sstats->nthreads += astats->nthreads;
593a4bd5210SJason Evans 	sstats->pactive += astats->pactive;
594a4bd5210SJason Evans 	sstats->pdirty += astats->pdirty;
595a4bd5210SJason Evans 
596df0d881dSJason Evans 	if (config_stats) {
597a4bd5210SJason Evans 		sstats->astats.mapped += astats->astats.mapped;
5981f0a49e8SJason Evans 		sstats->astats.retained += astats->astats.retained;
599a4bd5210SJason Evans 		sstats->astats.npurge += astats->astats.npurge;
600a4bd5210SJason Evans 		sstats->astats.nmadvise += astats->astats.nmadvise;
601a4bd5210SJason Evans 		sstats->astats.purged += astats->astats.purged;
602a4bd5210SJason Evans 
603df0d881dSJason Evans 		sstats->astats.metadata_mapped +=
604df0d881dSJason Evans 		    astats->astats.metadata_mapped;
605df0d881dSJason Evans 		sstats->astats.metadata_allocated +=
606df0d881dSJason Evans 		    astats->astats.metadata_allocated;
607d0e79aa3SJason Evans 
608a4bd5210SJason Evans 		sstats->allocated_small += astats->allocated_small;
609a4bd5210SJason Evans 		sstats->nmalloc_small += astats->nmalloc_small;
610a4bd5210SJason Evans 		sstats->ndalloc_small += astats->ndalloc_small;
611a4bd5210SJason Evans 		sstats->nrequests_small += astats->nrequests_small;
612a4bd5210SJason Evans 
613df0d881dSJason Evans 		sstats->astats.allocated_large +=
614df0d881dSJason Evans 		    astats->astats.allocated_large;
615a4bd5210SJason Evans 		sstats->astats.nmalloc_large += astats->astats.nmalloc_large;
616a4bd5210SJason Evans 		sstats->astats.ndalloc_large += astats->astats.ndalloc_large;
617df0d881dSJason Evans 		sstats->astats.nrequests_large +=
618df0d881dSJason Evans 		    astats->astats.nrequests_large;
619a4bd5210SJason Evans 
620d0e79aa3SJason Evans 		sstats->astats.allocated_huge += astats->astats.allocated_huge;
621d0e79aa3SJason Evans 		sstats->astats.nmalloc_huge += astats->astats.nmalloc_huge;
622d0e79aa3SJason Evans 		sstats->astats.ndalloc_huge += astats->astats.ndalloc_huge;
623a4bd5210SJason Evans 
624a4bd5210SJason Evans 		for (i = 0; i < NBINS; i++) {
625a4bd5210SJason Evans 			sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
626a4bd5210SJason Evans 			sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
627df0d881dSJason Evans 			sstats->bstats[i].nrequests +=
628df0d881dSJason Evans 			    astats->bstats[i].nrequests;
629d0e79aa3SJason Evans 			sstats->bstats[i].curregs += astats->bstats[i].curregs;
630a4bd5210SJason Evans 			if (config_tcache) {
631df0d881dSJason Evans 				sstats->bstats[i].nfills +=
632df0d881dSJason Evans 				    astats->bstats[i].nfills;
633a4bd5210SJason Evans 				sstats->bstats[i].nflushes +=
634a4bd5210SJason Evans 				    astats->bstats[i].nflushes;
635a4bd5210SJason Evans 			}
636a4bd5210SJason Evans 			sstats->bstats[i].nruns += astats->bstats[i].nruns;
637a4bd5210SJason Evans 			sstats->bstats[i].reruns += astats->bstats[i].reruns;
638a4bd5210SJason Evans 			sstats->bstats[i].curruns += astats->bstats[i].curruns;
639a4bd5210SJason Evans 		}
640d0e79aa3SJason Evans 
641d0e79aa3SJason Evans 		for (i = 0; i < nlclasses; i++) {
642d0e79aa3SJason Evans 			sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;
643d0e79aa3SJason Evans 			sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;
644df0d881dSJason Evans 			sstats->lstats[i].nrequests +=
645df0d881dSJason Evans 			    astats->lstats[i].nrequests;
646d0e79aa3SJason Evans 			sstats->lstats[i].curruns += astats->lstats[i].curruns;
647d0e79aa3SJason Evans 		}
648d0e79aa3SJason Evans 
649d0e79aa3SJason Evans 		for (i = 0; i < nhclasses; i++) {
650d0e79aa3SJason Evans 			sstats->hstats[i].nmalloc += astats->hstats[i].nmalloc;
651d0e79aa3SJason Evans 			sstats->hstats[i].ndalloc += astats->hstats[i].ndalloc;
652df0d881dSJason Evans 			sstats->hstats[i].curhchunks +=
653df0d881dSJason Evans 			    astats->hstats[i].curhchunks;
654df0d881dSJason Evans 		}
655d0e79aa3SJason Evans 	}
656a4bd5210SJason Evans }
657a4bd5210SJason Evans 
658a4bd5210SJason Evans static void
6591f0a49e8SJason Evans ctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, unsigned i)
660a4bd5210SJason Evans {
661a4bd5210SJason Evans 	ctl_arena_stats_t *astats = &ctl_stats.arenas[i];
66282872ac0SJason Evans 	ctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas];
663a4bd5210SJason Evans 
664a4bd5210SJason Evans 	ctl_arena_clear(astats);
6651f0a49e8SJason Evans 	ctl_arena_stats_amerge(tsdn, astats, arena);
666a4bd5210SJason Evans 	/* Merge into sum stats as well. */
667a4bd5210SJason Evans 	ctl_arena_stats_smerge(sstats, astats);
668a4bd5210SJason Evans }
669a4bd5210SJason Evans 
67082872ac0SJason Evans static bool
6711f0a49e8SJason Evans ctl_grow(tsdn_t *tsdn)
67282872ac0SJason Evans {
67382872ac0SJason Evans 	ctl_arena_stats_t *astats;
67482872ac0SJason Evans 
675d0e79aa3SJason Evans 	/* Initialize new arena. */
6761f0a49e8SJason Evans 	if (arena_init(tsdn, ctl_stats.narenas) == NULL)
677d0e79aa3SJason Evans 		return (true);
678d0e79aa3SJason Evans 
679d0e79aa3SJason Evans 	/* Allocate extended arena stats. */
680d0e79aa3SJason Evans 	astats = (ctl_arena_stats_t *)a0malloc((ctl_stats.narenas + 2) *
6812b06b201SJason Evans 	    sizeof(ctl_arena_stats_t));
68282872ac0SJason Evans 	if (astats == NULL)
68382872ac0SJason Evans 		return (true);
68482872ac0SJason Evans 
6852b06b201SJason Evans 	/* Initialize the new astats element. */
6862b06b201SJason Evans 	memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) *
6872b06b201SJason Evans 	    sizeof(ctl_arena_stats_t));
6882b06b201SJason Evans 	memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t));
6892b06b201SJason Evans 	if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) {
690d0e79aa3SJason Evans 		a0dalloc(astats);
69182872ac0SJason Evans 		return (true);
69282872ac0SJason Evans 	}
69382872ac0SJason Evans 	/* Swap merged stats to their new location. */
69482872ac0SJason Evans 	{
69582872ac0SJason Evans 		ctl_arena_stats_t tstats;
69682872ac0SJason Evans 		memcpy(&tstats, &astats[ctl_stats.narenas],
69782872ac0SJason Evans 		    sizeof(ctl_arena_stats_t));
69882872ac0SJason Evans 		memcpy(&astats[ctl_stats.narenas],
69982872ac0SJason Evans 		    &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t));
70082872ac0SJason Evans 		memcpy(&astats[ctl_stats.narenas + 1], &tstats,
70182872ac0SJason Evans 		    sizeof(ctl_arena_stats_t));
70282872ac0SJason Evans 	}
703d0e79aa3SJason Evans 	a0dalloc(ctl_stats.arenas);
7042b06b201SJason Evans 	ctl_stats.arenas = astats;
7052b06b201SJason Evans 	ctl_stats.narenas++;
70682872ac0SJason Evans 
70782872ac0SJason Evans 	return (false);
70882872ac0SJason Evans }
70982872ac0SJason Evans 
710a4bd5210SJason Evans static void
7111f0a49e8SJason Evans ctl_refresh(tsdn_t *tsdn)
712a4bd5210SJason Evans {
713a4bd5210SJason Evans 	unsigned i;
71482872ac0SJason Evans 	VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);
715a4bd5210SJason Evans 
716a4bd5210SJason Evans 	/*
717a4bd5210SJason Evans 	 * Clear sum stats, since they will be merged into by
718a4bd5210SJason Evans 	 * ctl_arena_refresh().
719a4bd5210SJason Evans 	 */
72082872ac0SJason Evans 	ctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]);
721a4bd5210SJason Evans 
722df0d881dSJason Evans 	for (i = 0; i < ctl_stats.narenas; i++)
7231f0a49e8SJason Evans 		tarenas[i] = arena_get(tsdn, i, false);
724d0e79aa3SJason Evans 
72582872ac0SJason Evans 	for (i = 0; i < ctl_stats.narenas; i++) {
726a4bd5210SJason Evans 		bool initialized = (tarenas[i] != NULL);
727a4bd5210SJason Evans 
728a4bd5210SJason Evans 		ctl_stats.arenas[i].initialized = initialized;
729a4bd5210SJason Evans 		if (initialized)
7301f0a49e8SJason Evans 			ctl_arena_refresh(tsdn, tarenas[i], i);
731a4bd5210SJason Evans 	}
732a4bd5210SJason Evans 
733a4bd5210SJason Evans 	if (config_stats) {
734d0e79aa3SJason Evans 		size_t base_allocated, base_resident, base_mapped;
7351f0a49e8SJason Evans 		base_stats_get(tsdn, &base_allocated, &base_resident,
7361f0a49e8SJason Evans 		    &base_mapped);
73782872ac0SJason Evans 		ctl_stats.allocated =
738d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].allocated_small +
739d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large +
740d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_huge;
74182872ac0SJason Evans 		ctl_stats.active =
742d0e79aa3SJason Evans 		    (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE);
743d0e79aa3SJason Evans 		ctl_stats.metadata = base_allocated +
744d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +
745d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats
746d0e79aa3SJason Evans 		    .metadata_allocated;
747d0e79aa3SJason Evans 		ctl_stats.resident = base_resident +
748d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +
749d0e79aa3SJason Evans 		    ((ctl_stats.arenas[ctl_stats.narenas].pactive +
750d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].pdirty) << LG_PAGE);
751d0e79aa3SJason Evans 		ctl_stats.mapped = base_mapped +
752d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.mapped;
7531f0a49e8SJason Evans 		ctl_stats.retained =
7541f0a49e8SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.retained;
755a4bd5210SJason Evans 	}
756a4bd5210SJason Evans 
757a4bd5210SJason Evans 	ctl_epoch++;
758a4bd5210SJason Evans }
759a4bd5210SJason Evans 
760a4bd5210SJason Evans static bool
7611f0a49e8SJason Evans ctl_init(tsdn_t *tsdn)
762a4bd5210SJason Evans {
763a4bd5210SJason Evans 	bool ret;
764a4bd5210SJason Evans 
7651f0a49e8SJason Evans 	malloc_mutex_lock(tsdn, &ctl_mtx);
766d0e79aa3SJason Evans 	if (!ctl_initialized) {
767a4bd5210SJason Evans 		/*
768a4bd5210SJason Evans 		 * Allocate space for one extra arena stats element, which
769a4bd5210SJason Evans 		 * contains summed stats across all arenas.
770a4bd5210SJason Evans 		 */
771d0e79aa3SJason Evans 		ctl_stats.narenas = narenas_total_get();
772d0e79aa3SJason Evans 		ctl_stats.arenas = (ctl_arena_stats_t *)a0malloc(
77382872ac0SJason Evans 		    (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t));
774a4bd5210SJason Evans 		if (ctl_stats.arenas == NULL) {
775a4bd5210SJason Evans 			ret = true;
776a4bd5210SJason Evans 			goto label_return;
777a4bd5210SJason Evans 		}
77882872ac0SJason Evans 		memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) *
779a4bd5210SJason Evans 		    sizeof(ctl_arena_stats_t));
780a4bd5210SJason Evans 
781a4bd5210SJason Evans 		/*
782a4bd5210SJason Evans 		 * Initialize all stats structures, regardless of whether they
783a4bd5210SJason Evans 		 * ever get used.  Lazy initialization would allow errors to
784a4bd5210SJason Evans 		 * cause inconsistent state to be viewable by the application.
785a4bd5210SJason Evans 		 */
786a4bd5210SJason Evans 		if (config_stats) {
787a4bd5210SJason Evans 			unsigned i;
78882872ac0SJason Evans 			for (i = 0; i <= ctl_stats.narenas; i++) {
789a4bd5210SJason Evans 				if (ctl_arena_init(&ctl_stats.arenas[i])) {
790d0e79aa3SJason Evans 					unsigned j;
791d0e79aa3SJason Evans 					for (j = 0; j < i; j++) {
792d0e79aa3SJason Evans 						a0dalloc(
793d0e79aa3SJason Evans 						    ctl_stats.arenas[j].lstats);
794d0e79aa3SJason Evans 						a0dalloc(
795d0e79aa3SJason Evans 						    ctl_stats.arenas[j].hstats);
796d0e79aa3SJason Evans 					}
797d0e79aa3SJason Evans 					a0dalloc(ctl_stats.arenas);
798d0e79aa3SJason Evans 					ctl_stats.arenas = NULL;
799a4bd5210SJason Evans 					ret = true;
800a4bd5210SJason Evans 					goto label_return;
801a4bd5210SJason Evans 				}
802a4bd5210SJason Evans 			}
803a4bd5210SJason Evans 		}
80482872ac0SJason Evans 		ctl_stats.arenas[ctl_stats.narenas].initialized = true;
805a4bd5210SJason Evans 
806a4bd5210SJason Evans 		ctl_epoch = 0;
8071f0a49e8SJason Evans 		ctl_refresh(tsdn);
808a4bd5210SJason Evans 		ctl_initialized = true;
809a4bd5210SJason Evans 	}
810a4bd5210SJason Evans 
811a4bd5210SJason Evans 	ret = false;
812a4bd5210SJason Evans label_return:
8131f0a49e8SJason Evans 	malloc_mutex_unlock(tsdn, &ctl_mtx);
814a4bd5210SJason Evans 	return (ret);
815a4bd5210SJason Evans }
816a4bd5210SJason Evans 
817a4bd5210SJason Evans static int
8181f0a49e8SJason Evans ctl_lookup(tsdn_t *tsdn, const char *name, ctl_node_t const **nodesp,
8191f0a49e8SJason Evans     size_t *mibp, size_t *depthp)
820a4bd5210SJason Evans {
821a4bd5210SJason Evans 	int ret;
822a4bd5210SJason Evans 	const char *elm, *tdot, *dot;
823a4bd5210SJason Evans 	size_t elen, i, j;
824e722f8f8SJason Evans 	const ctl_named_node_t *node;
825a4bd5210SJason Evans 
826a4bd5210SJason Evans 	elm = name;
827a4bd5210SJason Evans 	/* Equivalent to strchrnul(). */
828a4bd5210SJason Evans 	dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
829a4bd5210SJason Evans 	elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
830a4bd5210SJason Evans 	if (elen == 0) {
831a4bd5210SJason Evans 		ret = ENOENT;
832a4bd5210SJason Evans 		goto label_return;
833a4bd5210SJason Evans 	}
834a4bd5210SJason Evans 	node = super_root_node;
835a4bd5210SJason Evans 	for (i = 0; i < *depthp; i++) {
836e722f8f8SJason Evans 		assert(node);
837e722f8f8SJason Evans 		assert(node->nchildren > 0);
838e722f8f8SJason Evans 		if (ctl_named_node(node->children) != NULL) {
839e722f8f8SJason Evans 			const ctl_named_node_t *pnode = node;
840a4bd5210SJason Evans 
841a4bd5210SJason Evans 			/* Children are named. */
842e722f8f8SJason Evans 			for (j = 0; j < node->nchildren; j++) {
843e722f8f8SJason Evans 				const ctl_named_node_t *child =
844e722f8f8SJason Evans 				    ctl_named_children(node, j);
845e722f8f8SJason Evans 				if (strlen(child->name) == elen &&
846e722f8f8SJason Evans 				    strncmp(elm, child->name, elen) == 0) {
847a4bd5210SJason Evans 					node = child;
848a4bd5210SJason Evans 					if (nodesp != NULL)
849e722f8f8SJason Evans 						nodesp[i] =
850e722f8f8SJason Evans 						    (const ctl_node_t *)node;
851a4bd5210SJason Evans 					mibp[i] = j;
852a4bd5210SJason Evans 					break;
853a4bd5210SJason Evans 				}
854a4bd5210SJason Evans 			}
855a4bd5210SJason Evans 			if (node == pnode) {
856a4bd5210SJason Evans 				ret = ENOENT;
857a4bd5210SJason Evans 				goto label_return;
858a4bd5210SJason Evans 			}
859a4bd5210SJason Evans 		} else {
860a4bd5210SJason Evans 			uintmax_t index;
861e722f8f8SJason Evans 			const ctl_indexed_node_t *inode;
862a4bd5210SJason Evans 
863a4bd5210SJason Evans 			/* Children are indexed. */
864a4bd5210SJason Evans 			index = malloc_strtoumax(elm, NULL, 10);
865a4bd5210SJason Evans 			if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
866a4bd5210SJason Evans 				ret = ENOENT;
867a4bd5210SJason Evans 				goto label_return;
868a4bd5210SJason Evans 			}
869a4bd5210SJason Evans 
870e722f8f8SJason Evans 			inode = ctl_indexed_node(node->children);
8711f0a49e8SJason Evans 			node = inode->index(tsdn, mibp, *depthp, (size_t)index);
872a4bd5210SJason Evans 			if (node == NULL) {
873a4bd5210SJason Evans 				ret = ENOENT;
874a4bd5210SJason Evans 				goto label_return;
875a4bd5210SJason Evans 			}
876a4bd5210SJason Evans 
877a4bd5210SJason Evans 			if (nodesp != NULL)
878e722f8f8SJason Evans 				nodesp[i] = (const ctl_node_t *)node;
879a4bd5210SJason Evans 			mibp[i] = (size_t)index;
880a4bd5210SJason Evans 		}
881a4bd5210SJason Evans 
882a4bd5210SJason Evans 		if (node->ctl != NULL) {
883a4bd5210SJason Evans 			/* Terminal node. */
884a4bd5210SJason Evans 			if (*dot != '\0') {
885a4bd5210SJason Evans 				/*
886a4bd5210SJason Evans 				 * The name contains more elements than are
887a4bd5210SJason Evans 				 * in this path through the tree.
888a4bd5210SJason Evans 				 */
889a4bd5210SJason Evans 				ret = ENOENT;
890a4bd5210SJason Evans 				goto label_return;
891a4bd5210SJason Evans 			}
892a4bd5210SJason Evans 			/* Complete lookup successful. */
893a4bd5210SJason Evans 			*depthp = i + 1;
894a4bd5210SJason Evans 			break;
895a4bd5210SJason Evans 		}
896a4bd5210SJason Evans 
897a4bd5210SJason Evans 		/* Update elm. */
898a4bd5210SJason Evans 		if (*dot == '\0') {
899a4bd5210SJason Evans 			/* No more elements. */
900a4bd5210SJason Evans 			ret = ENOENT;
901a4bd5210SJason Evans 			goto label_return;
902a4bd5210SJason Evans 		}
903a4bd5210SJason Evans 		elm = &dot[1];
904a4bd5210SJason Evans 		dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
905a4bd5210SJason Evans 		    strchr(elm, '\0');
906a4bd5210SJason Evans 		elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
907a4bd5210SJason Evans 	}
908a4bd5210SJason Evans 
909a4bd5210SJason Evans 	ret = 0;
910a4bd5210SJason Evans label_return:
911a4bd5210SJason Evans 	return (ret);
912a4bd5210SJason Evans }
913a4bd5210SJason Evans 
914a4bd5210SJason Evans int
9151f0a49e8SJason Evans ctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp,
9161f0a49e8SJason Evans     void *newp, size_t newlen)
917a4bd5210SJason Evans {
918a4bd5210SJason Evans 	int ret;
919a4bd5210SJason Evans 	size_t depth;
920a4bd5210SJason Evans 	ctl_node_t const *nodes[CTL_MAX_DEPTH];
921a4bd5210SJason Evans 	size_t mib[CTL_MAX_DEPTH];
922e722f8f8SJason Evans 	const ctl_named_node_t *node;
923a4bd5210SJason Evans 
9241f0a49e8SJason Evans 	if (!ctl_initialized && ctl_init(tsd_tsdn(tsd))) {
925a4bd5210SJason Evans 		ret = EAGAIN;
926a4bd5210SJason Evans 		goto label_return;
927a4bd5210SJason Evans 	}
928a4bd5210SJason Evans 
929a4bd5210SJason Evans 	depth = CTL_MAX_DEPTH;
9301f0a49e8SJason Evans 	ret = ctl_lookup(tsd_tsdn(tsd), name, nodes, mib, &depth);
931a4bd5210SJason Evans 	if (ret != 0)
932a4bd5210SJason Evans 		goto label_return;
933a4bd5210SJason Evans 
934e722f8f8SJason Evans 	node = ctl_named_node(nodes[depth-1]);
935e722f8f8SJason Evans 	if (node != NULL && node->ctl)
9361f0a49e8SJason Evans 		ret = node->ctl(tsd, mib, depth, oldp, oldlenp, newp, newlen);
937e722f8f8SJason Evans 	else {
938a4bd5210SJason Evans 		/* The name refers to a partial path through the ctl tree. */
939a4bd5210SJason Evans 		ret = ENOENT;
940a4bd5210SJason Evans 	}
941a4bd5210SJason Evans 
942a4bd5210SJason Evans label_return:
943a4bd5210SJason Evans 	return(ret);
944a4bd5210SJason Evans }
945a4bd5210SJason Evans 
946a4bd5210SJason Evans int
9471f0a49e8SJason Evans ctl_nametomib(tsdn_t *tsdn, const char *name, size_t *mibp, size_t *miblenp)
948a4bd5210SJason Evans {
949a4bd5210SJason Evans 	int ret;
950a4bd5210SJason Evans 
9511f0a49e8SJason Evans 	if (!ctl_initialized && ctl_init(tsdn)) {
952a4bd5210SJason Evans 		ret = EAGAIN;
953a4bd5210SJason Evans 		goto label_return;
954a4bd5210SJason Evans 	}
955a4bd5210SJason Evans 
9561f0a49e8SJason Evans 	ret = ctl_lookup(tsdn, name, NULL, mibp, miblenp);
957a4bd5210SJason Evans label_return:
958a4bd5210SJason Evans 	return(ret);
959a4bd5210SJason Evans }
960a4bd5210SJason Evans 
961a4bd5210SJason Evans int
9621f0a49e8SJason Evans ctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
9631f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
964a4bd5210SJason Evans {
965a4bd5210SJason Evans 	int ret;
966e722f8f8SJason Evans 	const ctl_named_node_t *node;
967a4bd5210SJason Evans 	size_t i;
968a4bd5210SJason Evans 
9691f0a49e8SJason Evans 	if (!ctl_initialized && ctl_init(tsd_tsdn(tsd))) {
970a4bd5210SJason Evans 		ret = EAGAIN;
971a4bd5210SJason Evans 		goto label_return;
972a4bd5210SJason Evans 	}
973a4bd5210SJason Evans 
974a4bd5210SJason Evans 	/* Iterate down the tree. */
975a4bd5210SJason Evans 	node = super_root_node;
976a4bd5210SJason Evans 	for (i = 0; i < miblen; i++) {
977e722f8f8SJason Evans 		assert(node);
978e722f8f8SJason Evans 		assert(node->nchildren > 0);
979e722f8f8SJason Evans 		if (ctl_named_node(node->children) != NULL) {
980a4bd5210SJason Evans 			/* Children are named. */
981df0d881dSJason Evans 			if (node->nchildren <= (unsigned)mib[i]) {
982a4bd5210SJason Evans 				ret = ENOENT;
983a4bd5210SJason Evans 				goto label_return;
984a4bd5210SJason Evans 			}
985e722f8f8SJason Evans 			node = ctl_named_children(node, mib[i]);
986a4bd5210SJason Evans 		} else {
987e722f8f8SJason Evans 			const ctl_indexed_node_t *inode;
988a4bd5210SJason Evans 
989a4bd5210SJason Evans 			/* Indexed element. */
990e722f8f8SJason Evans 			inode = ctl_indexed_node(node->children);
9911f0a49e8SJason Evans 			node = inode->index(tsd_tsdn(tsd), mib, miblen, mib[i]);
992a4bd5210SJason Evans 			if (node == NULL) {
993a4bd5210SJason Evans 				ret = ENOENT;
994a4bd5210SJason Evans 				goto label_return;
995a4bd5210SJason Evans 			}
996a4bd5210SJason Evans 		}
997a4bd5210SJason Evans 	}
998a4bd5210SJason Evans 
999a4bd5210SJason Evans 	/* Call the ctl function. */
1000e722f8f8SJason Evans 	if (node && node->ctl)
10011f0a49e8SJason Evans 		ret = node->ctl(tsd, mib, miblen, oldp, oldlenp, newp, newlen);
1002e722f8f8SJason Evans 	else {
1003a4bd5210SJason Evans 		/* Partial MIB. */
1004a4bd5210SJason Evans 		ret = ENOENT;
1005a4bd5210SJason Evans 	}
1006a4bd5210SJason Evans 
1007a4bd5210SJason Evans label_return:
1008a4bd5210SJason Evans 	return(ret);
1009a4bd5210SJason Evans }
1010a4bd5210SJason Evans 
1011a4bd5210SJason Evans bool
1012a4bd5210SJason Evans ctl_boot(void)
1013a4bd5210SJason Evans {
1014a4bd5210SJason Evans 
10151f0a49e8SJason Evans 	if (malloc_mutex_init(&ctl_mtx, "ctl", WITNESS_RANK_CTL))
1016a4bd5210SJason Evans 		return (true);
1017a4bd5210SJason Evans 
1018a4bd5210SJason Evans 	ctl_initialized = false;
1019a4bd5210SJason Evans 
1020a4bd5210SJason Evans 	return (false);
1021a4bd5210SJason Evans }
1022a4bd5210SJason Evans 
102382872ac0SJason Evans void
10241f0a49e8SJason Evans ctl_prefork(tsdn_t *tsdn)
102582872ac0SJason Evans {
102682872ac0SJason Evans 
10271f0a49e8SJason Evans 	malloc_mutex_prefork(tsdn, &ctl_mtx);
102882872ac0SJason Evans }
102982872ac0SJason Evans 
103082872ac0SJason Evans void
10311f0a49e8SJason Evans ctl_postfork_parent(tsdn_t *tsdn)
103282872ac0SJason Evans {
103382872ac0SJason Evans 
10341f0a49e8SJason Evans 	malloc_mutex_postfork_parent(tsdn, &ctl_mtx);
103582872ac0SJason Evans }
103682872ac0SJason Evans 
103782872ac0SJason Evans void
10381f0a49e8SJason Evans ctl_postfork_child(tsdn_t *tsdn)
103982872ac0SJason Evans {
104082872ac0SJason Evans 
10411f0a49e8SJason Evans 	malloc_mutex_postfork_child(tsdn, &ctl_mtx);
104282872ac0SJason Evans }
104382872ac0SJason Evans 
1044a4bd5210SJason Evans /******************************************************************************/
1045a4bd5210SJason Evans /* *_ctl() functions. */
1046a4bd5210SJason Evans 
1047a4bd5210SJason Evans #define	READONLY()	do {						\
1048a4bd5210SJason Evans 	if (newp != NULL || newlen != 0) {				\
1049a4bd5210SJason Evans 		ret = EPERM;						\
1050a4bd5210SJason Evans 		goto label_return;					\
1051a4bd5210SJason Evans 	}								\
1052a4bd5210SJason Evans } while (0)
1053a4bd5210SJason Evans 
1054a4bd5210SJason Evans #define	WRITEONLY()	do {						\
1055a4bd5210SJason Evans 	if (oldp != NULL || oldlenp != NULL) {				\
1056a4bd5210SJason Evans 		ret = EPERM;						\
1057a4bd5210SJason Evans 		goto label_return;					\
1058a4bd5210SJason Evans 	}								\
1059a4bd5210SJason Evans } while (0)
1060a4bd5210SJason Evans 
1061d0e79aa3SJason Evans #define	READ_XOR_WRITE()	do {					\
1062d0e79aa3SJason Evans 	if ((oldp != NULL && oldlenp != NULL) && (newp != NULL ||	\
1063d0e79aa3SJason Evans 	    newlen != 0)) {						\
1064d0e79aa3SJason Evans 		ret = EPERM;						\
1065d0e79aa3SJason Evans 		goto label_return;					\
1066d0e79aa3SJason Evans 	}								\
1067d0e79aa3SJason Evans } while (0)
1068d0e79aa3SJason Evans 
1069a4bd5210SJason Evans #define	READ(v, t)	do {						\
1070a4bd5210SJason Evans 	if (oldp != NULL && oldlenp != NULL) {				\
1071a4bd5210SJason Evans 		if (*oldlenp != sizeof(t)) {				\
1072a4bd5210SJason Evans 			size_t	copylen = (sizeof(t) <= *oldlenp)	\
1073a4bd5210SJason Evans 			    ? sizeof(t) : *oldlenp;			\
107488ad2f8dSJason Evans 			memcpy(oldp, (void *)&(v), copylen);		\
1075a4bd5210SJason Evans 			ret = EINVAL;					\
1076a4bd5210SJason Evans 			goto label_return;				\
1077d0e79aa3SJason Evans 		}							\
107888ad2f8dSJason Evans 		*(t *)oldp = (v);					\
1079a4bd5210SJason Evans 	}								\
1080a4bd5210SJason Evans } while (0)
1081a4bd5210SJason Evans 
1082a4bd5210SJason Evans #define	WRITE(v, t)	do {						\
1083a4bd5210SJason Evans 	if (newp != NULL) {						\
1084a4bd5210SJason Evans 		if (newlen != sizeof(t)) {				\
1085a4bd5210SJason Evans 			ret = EINVAL;					\
1086a4bd5210SJason Evans 			goto label_return;				\
1087a4bd5210SJason Evans 		}							\
108888ad2f8dSJason Evans 		(v) = *(t *)newp;					\
1089a4bd5210SJason Evans 	}								\
1090a4bd5210SJason Evans } while (0)
1091a4bd5210SJason Evans 
1092a4bd5210SJason Evans /*
1093a4bd5210SJason Evans  * There's a lot of code duplication in the following macros due to limitations
1094a4bd5210SJason Evans  * in how nested cpp macros are expanded.
1095a4bd5210SJason Evans  */
1096a4bd5210SJason Evans #define	CTL_RO_CLGEN(c, l, n, v, t)					\
1097a4bd5210SJason Evans static int								\
10981f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
10991f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1100a4bd5210SJason Evans {									\
1101a4bd5210SJason Evans 	int ret;							\
1102a4bd5210SJason Evans 	t oldval;							\
1103a4bd5210SJason Evans 									\
1104d0e79aa3SJason Evans 	if (!(c))							\
1105a4bd5210SJason Evans 		return (ENOENT);					\
1106a4bd5210SJason Evans 	if (l)								\
11071f0a49e8SJason Evans 		malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);		\
1108a4bd5210SJason Evans 	READONLY();							\
110988ad2f8dSJason Evans 	oldval = (v);							\
1110a4bd5210SJason Evans 	READ(oldval, t);						\
1111a4bd5210SJason Evans 									\
1112a4bd5210SJason Evans 	ret = 0;							\
1113a4bd5210SJason Evans label_return:								\
1114a4bd5210SJason Evans 	if (l)								\
11151f0a49e8SJason Evans 		malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);		\
1116a4bd5210SJason Evans 	return (ret);							\
1117a4bd5210SJason Evans }
1118a4bd5210SJason Evans 
1119a4bd5210SJason Evans #define	CTL_RO_CGEN(c, n, v, t)						\
1120a4bd5210SJason Evans static int								\
11211f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11221f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1123a4bd5210SJason Evans {									\
1124a4bd5210SJason Evans 	int ret;							\
1125a4bd5210SJason Evans 	t oldval;							\
1126a4bd5210SJason Evans 									\
1127d0e79aa3SJason Evans 	if (!(c))							\
1128a4bd5210SJason Evans 		return (ENOENT);					\
11291f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);			\
1130a4bd5210SJason Evans 	READONLY();							\
113188ad2f8dSJason Evans 	oldval = (v);							\
1132a4bd5210SJason Evans 	READ(oldval, t);						\
1133a4bd5210SJason Evans 									\
1134a4bd5210SJason Evans 	ret = 0;							\
1135a4bd5210SJason Evans label_return:								\
11361f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);			\
1137a4bd5210SJason Evans 	return (ret);							\
1138a4bd5210SJason Evans }
1139a4bd5210SJason Evans 
1140a4bd5210SJason Evans #define	CTL_RO_GEN(n, v, t)						\
1141a4bd5210SJason Evans static int								\
11421f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11431f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1144a4bd5210SJason Evans {									\
1145a4bd5210SJason Evans 	int ret;							\
1146a4bd5210SJason Evans 	t oldval;							\
1147a4bd5210SJason Evans 									\
11481f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);			\
1149a4bd5210SJason Evans 	READONLY();							\
115088ad2f8dSJason Evans 	oldval = (v);							\
1151a4bd5210SJason Evans 	READ(oldval, t);						\
1152a4bd5210SJason Evans 									\
1153a4bd5210SJason Evans 	ret = 0;							\
1154a4bd5210SJason Evans label_return:								\
11551f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);			\
1156a4bd5210SJason Evans 	return (ret);							\
1157a4bd5210SJason Evans }
1158a4bd5210SJason Evans 
1159a4bd5210SJason Evans /*
1160a4bd5210SJason Evans  * ctl_mtx is not acquired, under the assumption that no pertinent data will
1161a4bd5210SJason Evans  * mutate during the call.
1162a4bd5210SJason Evans  */
1163a4bd5210SJason Evans #define	CTL_RO_NL_CGEN(c, n, v, t)					\
1164a4bd5210SJason Evans static int								\
11651f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11661f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1167a4bd5210SJason Evans {									\
1168a4bd5210SJason Evans 	int ret;							\
1169a4bd5210SJason Evans 	t oldval;							\
1170a4bd5210SJason Evans 									\
1171d0e79aa3SJason Evans 	if (!(c))							\
1172a4bd5210SJason Evans 		return (ENOENT);					\
1173a4bd5210SJason Evans 	READONLY();							\
117488ad2f8dSJason Evans 	oldval = (v);							\
1175a4bd5210SJason Evans 	READ(oldval, t);						\
1176a4bd5210SJason Evans 									\
1177a4bd5210SJason Evans 	ret = 0;							\
1178a4bd5210SJason Evans label_return:								\
1179a4bd5210SJason Evans 	return (ret);							\
1180a4bd5210SJason Evans }
1181a4bd5210SJason Evans 
1182a4bd5210SJason Evans #define	CTL_RO_NL_GEN(n, v, t)						\
1183a4bd5210SJason Evans static int								\
11841f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11851f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1186a4bd5210SJason Evans {									\
1187a4bd5210SJason Evans 	int ret;							\
1188a4bd5210SJason Evans 	t oldval;							\
1189a4bd5210SJason Evans 									\
1190a4bd5210SJason Evans 	READONLY();							\
119188ad2f8dSJason Evans 	oldval = (v);							\
1192a4bd5210SJason Evans 	READ(oldval, t);						\
1193a4bd5210SJason Evans 									\
1194a4bd5210SJason Evans 	ret = 0;							\
1195a4bd5210SJason Evans label_return:								\
1196a4bd5210SJason Evans 	return (ret);							\
1197a4bd5210SJason Evans }
1198a4bd5210SJason Evans 
1199d0e79aa3SJason Evans #define	CTL_TSD_RO_NL_CGEN(c, n, m, t)					\
1200d0e79aa3SJason Evans static int								\
12011f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
12021f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1203d0e79aa3SJason Evans {									\
1204d0e79aa3SJason Evans 	int ret;							\
1205d0e79aa3SJason Evans 	t oldval;							\
1206d0e79aa3SJason Evans 									\
1207d0e79aa3SJason Evans 	if (!(c))							\
1208d0e79aa3SJason Evans 		return (ENOENT);					\
1209d0e79aa3SJason Evans 	READONLY();							\
1210d0e79aa3SJason Evans 	oldval = (m(tsd));						\
1211d0e79aa3SJason Evans 	READ(oldval, t);						\
1212d0e79aa3SJason Evans 									\
1213d0e79aa3SJason Evans 	ret = 0;							\
1214d0e79aa3SJason Evans label_return:								\
1215d0e79aa3SJason Evans 	return (ret);							\
1216d0e79aa3SJason Evans }
1217d0e79aa3SJason Evans 
1218df0d881dSJason Evans #define	CTL_RO_CONFIG_GEN(n, t)						\
1219a4bd5210SJason Evans static int								\
12201f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
12211f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1222a4bd5210SJason Evans {									\
1223a4bd5210SJason Evans 	int ret;							\
1224df0d881dSJason Evans 	t oldval;							\
1225a4bd5210SJason Evans 									\
1226a4bd5210SJason Evans 	READONLY();							\
1227a4bd5210SJason Evans 	oldval = n;							\
1228df0d881dSJason Evans 	READ(oldval, t);						\
1229a4bd5210SJason Evans 									\
1230a4bd5210SJason Evans 	ret = 0;							\
1231a4bd5210SJason Evans label_return:								\
1232a4bd5210SJason Evans 	return (ret);							\
1233a4bd5210SJason Evans }
1234a4bd5210SJason Evans 
1235f921d10fSJason Evans /******************************************************************************/
1236f921d10fSJason Evans 
1237a4bd5210SJason Evans CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
1238a4bd5210SJason Evans 
1239a4bd5210SJason Evans static int
12401f0a49e8SJason Evans epoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
12411f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1242a4bd5210SJason Evans {
1243a4bd5210SJason Evans 	int ret;
12442b06b201SJason Evans 	UNUSED uint64_t newval;
1245a4bd5210SJason Evans 
12461f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1247a4bd5210SJason Evans 	WRITE(newval, uint64_t);
1248e722f8f8SJason Evans 	if (newp != NULL)
12491f0a49e8SJason Evans 		ctl_refresh(tsd_tsdn(tsd));
1250a4bd5210SJason Evans 	READ(ctl_epoch, uint64_t);
1251a4bd5210SJason Evans 
1252a4bd5210SJason Evans 	ret = 0;
1253a4bd5210SJason Evans label_return:
12541f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1255a4bd5210SJason Evans 	return (ret);
1256a4bd5210SJason Evans }
1257a4bd5210SJason Evans 
1258f921d10fSJason Evans /******************************************************************************/
1259a4bd5210SJason Evans 
1260df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_cache_oblivious, bool)
1261df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_debug, bool)
1262df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_fill, bool)
1263df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_lazy_lock, bool)
1264df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_malloc_conf, const char *)
1265df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_munmap, bool)
1266df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof, bool)
1267df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
1268df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
1269df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_stats, bool)
1270df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_tcache, bool)
1271df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_tls, bool)
1272df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_utrace, bool)
1273df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_valgrind, bool)
1274df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_xmalloc, bool)
1275a4bd5210SJason Evans 
1276f921d10fSJason Evans /******************************************************************************/
1277a4bd5210SJason Evans 
1278f921d10fSJason Evans CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
1279f921d10fSJason Evans CTL_RO_NL_GEN(opt_dss, opt_dss, const char *)
1280f921d10fSJason Evans CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
1281df0d881dSJason Evans CTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned)
1282df0d881dSJason Evans CTL_RO_NL_GEN(opt_purge, purge_mode_names[opt_purge], const char *)
1283f921d10fSJason Evans CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
1284df0d881dSJason Evans CTL_RO_NL_GEN(opt_decay_time, opt_decay_time, ssize_t)
1285f921d10fSJason Evans CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
1286d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)
1287f921d10fSJason Evans CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
1288f921d10fSJason Evans CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
1289f921d10fSJason Evans CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
1290f921d10fSJason Evans CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
1291f921d10fSJason Evans CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
1292f921d10fSJason Evans CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
1293f921d10fSJason Evans CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
1294f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
1295f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
1296d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool)
1297d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
1298d0e79aa3SJason Evans     opt_prof_thread_active_init, bool)
1299f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
1300f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
1301f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
1302f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
1303f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
1304f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
1305a4bd5210SJason Evans 
1306f921d10fSJason Evans /******************************************************************************/
1307a4bd5210SJason Evans 
1308a4bd5210SJason Evans static int
13091f0a49e8SJason Evans thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
13101f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1311a4bd5210SJason Evans {
1312a4bd5210SJason Evans 	int ret;
1313d0e79aa3SJason Evans 	arena_t *oldarena;
1314a4bd5210SJason Evans 	unsigned newind, oldind;
1315a4bd5210SJason Evans 
1316d0e79aa3SJason Evans 	oldarena = arena_choose(tsd, NULL);
1317d0e79aa3SJason Evans 	if (oldarena == NULL)
1318d0e79aa3SJason Evans 		return (EAGAIN);
1319d0e79aa3SJason Evans 
13201f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1321d0e79aa3SJason Evans 	newind = oldind = oldarena->ind;
1322a4bd5210SJason Evans 	WRITE(newind, unsigned);
1323a4bd5210SJason Evans 	READ(oldind, unsigned);
1324a4bd5210SJason Evans 	if (newind != oldind) {
1325d0e79aa3SJason Evans 		arena_t *newarena;
1326a4bd5210SJason Evans 
132782872ac0SJason Evans 		if (newind >= ctl_stats.narenas) {
1328a4bd5210SJason Evans 			/* New arena index is out of range. */
1329a4bd5210SJason Evans 			ret = EFAULT;
1330a4bd5210SJason Evans 			goto label_return;
1331a4bd5210SJason Evans 		}
1332a4bd5210SJason Evans 
1333a4bd5210SJason Evans 		/* Initialize arena if necessary. */
13341f0a49e8SJason Evans 		newarena = arena_get(tsd_tsdn(tsd), newind, true);
1335d0e79aa3SJason Evans 		if (newarena == NULL) {
1336a4bd5210SJason Evans 			ret = EAGAIN;
1337a4bd5210SJason Evans 			goto label_return;
1338a4bd5210SJason Evans 		}
1339d0e79aa3SJason Evans 		/* Set new arena/tcache associations. */
1340d0e79aa3SJason Evans 		arena_migrate(tsd, oldind, newind);
1341a4bd5210SJason Evans 		if (config_tcache) {
1342d0e79aa3SJason Evans 			tcache_t *tcache = tsd_tcache_get(tsd);
1343d0e79aa3SJason Evans 			if (tcache != NULL) {
13441f0a49e8SJason Evans 				tcache_arena_reassociate(tsd_tsdn(tsd), tcache,
13451f0a49e8SJason Evans 				    oldarena, newarena);
1346a4bd5210SJason Evans 			}
1347a4bd5210SJason Evans 		}
1348a4bd5210SJason Evans 	}
1349a4bd5210SJason Evans 
1350a4bd5210SJason Evans 	ret = 0;
1351a4bd5210SJason Evans label_return:
13521f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1353a4bd5210SJason Evans 	return (ret);
1354a4bd5210SJason Evans }
1355a4bd5210SJason Evans 
1356d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_allocated, tsd_thread_allocated_get,
1357d0e79aa3SJason Evans     uint64_t)
1358d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_allocatedp, tsd_thread_allocatedp_get,
1359d0e79aa3SJason Evans     uint64_t *)
1360d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocated, tsd_thread_deallocated_get,
1361d0e79aa3SJason Evans     uint64_t)
1362d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp,
1363d0e79aa3SJason Evans     tsd_thread_deallocatedp_get, uint64_t *)
1364a4bd5210SJason Evans 
1365f921d10fSJason Evans static int
13661f0a49e8SJason Evans thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
13671f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1368f921d10fSJason Evans {
1369f921d10fSJason Evans 	int ret;
1370f921d10fSJason Evans 	bool oldval;
1371a4bd5210SJason Evans 
1372d0e79aa3SJason Evans 	if (!config_tcache)
1373f921d10fSJason Evans 		return (ENOENT);
1374a4bd5210SJason Evans 
1375f921d10fSJason Evans 	oldval = tcache_enabled_get();
1376f921d10fSJason Evans 	if (newp != NULL) {
1377f921d10fSJason Evans 		if (newlen != sizeof(bool)) {
1378f921d10fSJason Evans 			ret = EINVAL;
1379f921d10fSJason Evans 			goto label_return;
1380f921d10fSJason Evans 		}
1381f921d10fSJason Evans 		tcache_enabled_set(*(bool *)newp);
1382f921d10fSJason Evans 	}
1383f921d10fSJason Evans 	READ(oldval, bool);
1384a4bd5210SJason Evans 
1385f921d10fSJason Evans 	ret = 0;
1386f921d10fSJason Evans label_return:
1387f921d10fSJason Evans 	return (ret);
1388f921d10fSJason Evans }
1389f921d10fSJason Evans 
1390f921d10fSJason Evans static int
13911f0a49e8SJason Evans thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
13921f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1393f921d10fSJason Evans {
1394f921d10fSJason Evans 	int ret;
1395f921d10fSJason Evans 
1396d0e79aa3SJason Evans 	if (!config_tcache)
1397f921d10fSJason Evans 		return (ENOENT);
1398f921d10fSJason Evans 
1399f921d10fSJason Evans 	READONLY();
1400f921d10fSJason Evans 	WRITEONLY();
1401f921d10fSJason Evans 
1402f921d10fSJason Evans 	tcache_flush();
1403f921d10fSJason Evans 
1404f921d10fSJason Evans 	ret = 0;
1405f921d10fSJason Evans label_return:
1406f921d10fSJason Evans 	return (ret);
1407f921d10fSJason Evans }
1408a4bd5210SJason Evans 
1409d0e79aa3SJason Evans static int
14101f0a49e8SJason Evans thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1411d0e79aa3SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1412d0e79aa3SJason Evans {
1413d0e79aa3SJason Evans 	int ret;
1414d0e79aa3SJason Evans 
1415d0e79aa3SJason Evans 	if (!config_prof)
1416d0e79aa3SJason Evans 		return (ENOENT);
1417d0e79aa3SJason Evans 
1418d0e79aa3SJason Evans 	READ_XOR_WRITE();
1419d0e79aa3SJason Evans 
1420d0e79aa3SJason Evans 	if (newp != NULL) {
1421d0e79aa3SJason Evans 		if (newlen != sizeof(const char *)) {
1422d0e79aa3SJason Evans 			ret = EINVAL;
1423d0e79aa3SJason Evans 			goto label_return;
1424d0e79aa3SJason Evans 		}
1425d0e79aa3SJason Evans 
1426d0e79aa3SJason Evans 		if ((ret = prof_thread_name_set(tsd, *(const char **)newp)) !=
1427d0e79aa3SJason Evans 		    0)
1428d0e79aa3SJason Evans 			goto label_return;
1429d0e79aa3SJason Evans 	} else {
14301f0a49e8SJason Evans 		const char *oldname = prof_thread_name_get(tsd);
1431d0e79aa3SJason Evans 		READ(oldname, const char *);
1432d0e79aa3SJason Evans 	}
1433d0e79aa3SJason Evans 
1434d0e79aa3SJason Evans 	ret = 0;
1435d0e79aa3SJason Evans label_return:
1436d0e79aa3SJason Evans 	return (ret);
1437d0e79aa3SJason Evans }
1438d0e79aa3SJason Evans 
1439d0e79aa3SJason Evans static int
14401f0a49e8SJason Evans thread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1441d0e79aa3SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1442d0e79aa3SJason Evans {
1443d0e79aa3SJason Evans 	int ret;
1444d0e79aa3SJason Evans 	bool oldval;
1445d0e79aa3SJason Evans 
1446d0e79aa3SJason Evans 	if (!config_prof)
1447d0e79aa3SJason Evans 		return (ENOENT);
1448d0e79aa3SJason Evans 
14491f0a49e8SJason Evans 	oldval = prof_thread_active_get(tsd);
1450d0e79aa3SJason Evans 	if (newp != NULL) {
1451d0e79aa3SJason Evans 		if (newlen != sizeof(bool)) {
1452d0e79aa3SJason Evans 			ret = EINVAL;
1453d0e79aa3SJason Evans 			goto label_return;
1454d0e79aa3SJason Evans 		}
14551f0a49e8SJason Evans 		if (prof_thread_active_set(tsd, *(bool *)newp)) {
1456d0e79aa3SJason Evans 			ret = EAGAIN;
1457d0e79aa3SJason Evans 			goto label_return;
1458d0e79aa3SJason Evans 		}
1459d0e79aa3SJason Evans 	}
1460d0e79aa3SJason Evans 	READ(oldval, bool);
1461d0e79aa3SJason Evans 
1462d0e79aa3SJason Evans 	ret = 0;
1463d0e79aa3SJason Evans label_return:
1464d0e79aa3SJason Evans 	return (ret);
1465d0e79aa3SJason Evans }
1466d0e79aa3SJason Evans 
1467d0e79aa3SJason Evans /******************************************************************************/
1468d0e79aa3SJason Evans 
1469d0e79aa3SJason Evans static int
14701f0a49e8SJason Evans tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
14711f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1472d0e79aa3SJason Evans {
1473d0e79aa3SJason Evans 	int ret;
1474d0e79aa3SJason Evans 	unsigned tcache_ind;
1475d0e79aa3SJason Evans 
1476d0e79aa3SJason Evans 	if (!config_tcache)
1477d0e79aa3SJason Evans 		return (ENOENT);
1478d0e79aa3SJason Evans 
14791f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1480d0e79aa3SJason Evans 	READONLY();
1481*bde95144SJason Evans 	if (tcaches_create(tsd, &tcache_ind)) {
1482d0e79aa3SJason Evans 		ret = EFAULT;
1483d0e79aa3SJason Evans 		goto label_return;
1484d0e79aa3SJason Evans 	}
1485d0e79aa3SJason Evans 	READ(tcache_ind, unsigned);
1486d0e79aa3SJason Evans 
1487d0e79aa3SJason Evans 	ret = 0;
1488d0e79aa3SJason Evans label_return:
14891f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1490d0e79aa3SJason Evans 	return (ret);
1491d0e79aa3SJason Evans }
1492d0e79aa3SJason Evans 
1493d0e79aa3SJason Evans static int
14941f0a49e8SJason Evans tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
14951f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1496d0e79aa3SJason Evans {
1497d0e79aa3SJason Evans 	int ret;
1498d0e79aa3SJason Evans 	unsigned tcache_ind;
1499d0e79aa3SJason Evans 
1500d0e79aa3SJason Evans 	if (!config_tcache)
1501d0e79aa3SJason Evans 		return (ENOENT);
1502d0e79aa3SJason Evans 
1503d0e79aa3SJason Evans 	WRITEONLY();
1504d0e79aa3SJason Evans 	tcache_ind = UINT_MAX;
1505d0e79aa3SJason Evans 	WRITE(tcache_ind, unsigned);
1506d0e79aa3SJason Evans 	if (tcache_ind == UINT_MAX) {
1507d0e79aa3SJason Evans 		ret = EFAULT;
1508d0e79aa3SJason Evans 		goto label_return;
1509d0e79aa3SJason Evans 	}
1510d0e79aa3SJason Evans 	tcaches_flush(tsd, tcache_ind);
1511d0e79aa3SJason Evans 
1512d0e79aa3SJason Evans 	ret = 0;
1513d0e79aa3SJason Evans label_return:
1514d0e79aa3SJason Evans 	return (ret);
1515d0e79aa3SJason Evans }
1516d0e79aa3SJason Evans 
1517d0e79aa3SJason Evans static int
15181f0a49e8SJason Evans tcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1519d0e79aa3SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1520d0e79aa3SJason Evans {
1521d0e79aa3SJason Evans 	int ret;
1522d0e79aa3SJason Evans 	unsigned tcache_ind;
1523d0e79aa3SJason Evans 
1524d0e79aa3SJason Evans 	if (!config_tcache)
1525d0e79aa3SJason Evans 		return (ENOENT);
1526d0e79aa3SJason Evans 
1527d0e79aa3SJason Evans 	WRITEONLY();
1528d0e79aa3SJason Evans 	tcache_ind = UINT_MAX;
1529d0e79aa3SJason Evans 	WRITE(tcache_ind, unsigned);
1530d0e79aa3SJason Evans 	if (tcache_ind == UINT_MAX) {
1531d0e79aa3SJason Evans 		ret = EFAULT;
1532d0e79aa3SJason Evans 		goto label_return;
1533d0e79aa3SJason Evans 	}
1534d0e79aa3SJason Evans 	tcaches_destroy(tsd, tcache_ind);
1535d0e79aa3SJason Evans 
1536d0e79aa3SJason Evans 	ret = 0;
1537d0e79aa3SJason Evans label_return:
1538d0e79aa3SJason Evans 	return (ret);
1539d0e79aa3SJason Evans }
1540d0e79aa3SJason Evans 
1541a4bd5210SJason Evans /******************************************************************************/
1542a4bd5210SJason Evans 
154382872ac0SJason Evans static void
15441f0a49e8SJason Evans arena_i_purge(tsdn_t *tsdn, unsigned arena_ind, bool all)
154582872ac0SJason Evans {
154682872ac0SJason Evans 
15471f0a49e8SJason Evans 	malloc_mutex_lock(tsdn, &ctl_mtx);
1548df0d881dSJason Evans 	{
1549df0d881dSJason Evans 		unsigned narenas = ctl_stats.narenas;
155082872ac0SJason Evans 
1551df0d881dSJason Evans 		if (arena_ind == narenas) {
155282872ac0SJason Evans 			unsigned i;
1553df0d881dSJason Evans 			VARIABLE_ARRAY(arena_t *, tarenas, narenas);
1554df0d881dSJason Evans 
1555df0d881dSJason Evans 			for (i = 0; i < narenas; i++)
15561f0a49e8SJason Evans 				tarenas[i] = arena_get(tsdn, i, false);
1557df0d881dSJason Evans 
1558df0d881dSJason Evans 			/*
1559df0d881dSJason Evans 			 * No further need to hold ctl_mtx, since narenas and
1560df0d881dSJason Evans 			 * tarenas contain everything needed below.
1561df0d881dSJason Evans 			 */
15621f0a49e8SJason Evans 			malloc_mutex_unlock(tsdn, &ctl_mtx);
1563df0d881dSJason Evans 
1564df0d881dSJason Evans 			for (i = 0; i < narenas; i++) {
156582872ac0SJason Evans 				if (tarenas[i] != NULL)
15661f0a49e8SJason Evans 					arena_purge(tsdn, tarenas[i], all);
156782872ac0SJason Evans 			}
156882872ac0SJason Evans 		} else {
1569df0d881dSJason Evans 			arena_t *tarena;
1570df0d881dSJason Evans 
1571df0d881dSJason Evans 			assert(arena_ind < narenas);
1572df0d881dSJason Evans 
15731f0a49e8SJason Evans 			tarena = arena_get(tsdn, arena_ind, false);
1574df0d881dSJason Evans 
1575df0d881dSJason Evans 			/* No further need to hold ctl_mtx. */
15761f0a49e8SJason Evans 			malloc_mutex_unlock(tsdn, &ctl_mtx);
1577df0d881dSJason Evans 
1578df0d881dSJason Evans 			if (tarena != NULL)
15791f0a49e8SJason Evans 				arena_purge(tsdn, tarena, all);
1580df0d881dSJason Evans 		}
158182872ac0SJason Evans 	}
158282872ac0SJason Evans }
158382872ac0SJason Evans 
158482872ac0SJason Evans static int
15851f0a49e8SJason Evans arena_i_purge_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
15861f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
158782872ac0SJason Evans {
158882872ac0SJason Evans 	int ret;
158982872ac0SJason Evans 
159082872ac0SJason Evans 	READONLY();
159182872ac0SJason Evans 	WRITEONLY();
15921f0a49e8SJason Evans 	arena_i_purge(tsd_tsdn(tsd), (unsigned)mib[1], true);
1593df0d881dSJason Evans 
1594df0d881dSJason Evans 	ret = 0;
1595df0d881dSJason Evans label_return:
1596df0d881dSJason Evans 	return (ret);
1597df0d881dSJason Evans }
1598df0d881dSJason Evans 
1599df0d881dSJason Evans static int
16001f0a49e8SJason Evans arena_i_decay_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
16011f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1602df0d881dSJason Evans {
1603df0d881dSJason Evans 	int ret;
1604df0d881dSJason Evans 
1605df0d881dSJason Evans 	READONLY();
1606df0d881dSJason Evans 	WRITEONLY();
16071f0a49e8SJason Evans 	arena_i_purge(tsd_tsdn(tsd), (unsigned)mib[1], false);
160882872ac0SJason Evans 
160982872ac0SJason Evans 	ret = 0;
161082872ac0SJason Evans label_return:
161182872ac0SJason Evans 	return (ret);
161282872ac0SJason Evans }
161382872ac0SJason Evans 
161482872ac0SJason Evans static int
16151f0a49e8SJason Evans arena_i_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
16161f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
16171f0a49e8SJason Evans {
16181f0a49e8SJason Evans 	int ret;
16191f0a49e8SJason Evans 	unsigned arena_ind;
16201f0a49e8SJason Evans 	arena_t *arena;
16211f0a49e8SJason Evans 
16221f0a49e8SJason Evans 	READONLY();
16231f0a49e8SJason Evans 	WRITEONLY();
16241f0a49e8SJason Evans 
16251f0a49e8SJason Evans 	if ((config_valgrind && unlikely(in_valgrind)) || (config_fill &&
16261f0a49e8SJason Evans 	    unlikely(opt_quarantine))) {
16271f0a49e8SJason Evans 		ret = EFAULT;
16281f0a49e8SJason Evans 		goto label_return;
16291f0a49e8SJason Evans 	}
16301f0a49e8SJason Evans 
16311f0a49e8SJason Evans 	arena_ind = (unsigned)mib[1];
16321f0a49e8SJason Evans 	if (config_debug) {
16331f0a49e8SJason Evans 		malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
16341f0a49e8SJason Evans 		assert(arena_ind < ctl_stats.narenas);
16351f0a49e8SJason Evans 		malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
16361f0a49e8SJason Evans 	}
16371f0a49e8SJason Evans 	assert(arena_ind >= opt_narenas);
16381f0a49e8SJason Evans 
16391f0a49e8SJason Evans 	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
16401f0a49e8SJason Evans 
16411f0a49e8SJason Evans 	arena_reset(tsd, arena);
16421f0a49e8SJason Evans 
16431f0a49e8SJason Evans 	ret = 0;
16441f0a49e8SJason Evans label_return:
16451f0a49e8SJason Evans 	return (ret);
16461f0a49e8SJason Evans }
16471f0a49e8SJason Evans 
16481f0a49e8SJason Evans static int
16491f0a49e8SJason Evans arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
16501f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
165182872ac0SJason Evans {
1652d0e79aa3SJason Evans 	int ret;
1653d0e79aa3SJason Evans 	const char *dss = NULL;
1654df0d881dSJason Evans 	unsigned arena_ind = (unsigned)mib[1];
165582872ac0SJason Evans 	dss_prec_t dss_prec_old = dss_prec_limit;
165682872ac0SJason Evans 	dss_prec_t dss_prec = dss_prec_limit;
165782872ac0SJason Evans 
16581f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
165982872ac0SJason Evans 	WRITE(dss, const char *);
1660d0e79aa3SJason Evans 	if (dss != NULL) {
1661d0e79aa3SJason Evans 		int i;
1662d0e79aa3SJason Evans 		bool match = false;
1663d0e79aa3SJason Evans 
166482872ac0SJason Evans 		for (i = 0; i < dss_prec_limit; i++) {
166582872ac0SJason Evans 			if (strcmp(dss_prec_names[i], dss) == 0) {
166682872ac0SJason Evans 				dss_prec = i;
166782872ac0SJason Evans 				match = true;
166882872ac0SJason Evans 				break;
166982872ac0SJason Evans 			}
167082872ac0SJason Evans 		}
1671d0e79aa3SJason Evans 
1672d0e79aa3SJason Evans 		if (!match) {
167382872ac0SJason Evans 			ret = EINVAL;
167482872ac0SJason Evans 			goto label_return;
167582872ac0SJason Evans 		}
1676d0e79aa3SJason Evans 	}
167782872ac0SJason Evans 
167882872ac0SJason Evans 	if (arena_ind < ctl_stats.narenas) {
16791f0a49e8SJason Evans 		arena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1680d0e79aa3SJason Evans 		if (arena == NULL || (dss_prec != dss_prec_limit &&
16811f0a49e8SJason Evans 		    arena_dss_prec_set(tsd_tsdn(tsd), arena, dss_prec))) {
1682d0e79aa3SJason Evans 			ret = EFAULT;
1683d0e79aa3SJason Evans 			goto label_return;
168482872ac0SJason Evans 		}
16851f0a49e8SJason Evans 		dss_prec_old = arena_dss_prec_get(tsd_tsdn(tsd), arena);
1686d0e79aa3SJason Evans 	} else {
1687d0e79aa3SJason Evans 		if (dss_prec != dss_prec_limit &&
1688*bde95144SJason Evans 		    chunk_dss_prec_set(dss_prec)) {
1689d0e79aa3SJason Evans 			ret = EFAULT;
1690d0e79aa3SJason Evans 			goto label_return;
1691d0e79aa3SJason Evans 		}
1692*bde95144SJason Evans 		dss_prec_old = chunk_dss_prec_get();
1693d0e79aa3SJason Evans 	}
1694d0e79aa3SJason Evans 
169582872ac0SJason Evans 	dss = dss_prec_names[dss_prec_old];
169682872ac0SJason Evans 	READ(dss, const char *);
1697d0e79aa3SJason Evans 
1698d0e79aa3SJason Evans 	ret = 0;
1699d0e79aa3SJason Evans label_return:
17001f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1701d0e79aa3SJason Evans 	return (ret);
1702d0e79aa3SJason Evans }
1703d0e79aa3SJason Evans 
1704d0e79aa3SJason Evans static int
17051f0a49e8SJason Evans arena_i_lg_dirty_mult_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
17061f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1707d0e79aa3SJason Evans {
1708d0e79aa3SJason Evans 	int ret;
1709df0d881dSJason Evans 	unsigned arena_ind = (unsigned)mib[1];
1710d0e79aa3SJason Evans 	arena_t *arena;
1711d0e79aa3SJason Evans 
17121f0a49e8SJason Evans 	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1713d0e79aa3SJason Evans 	if (arena == NULL) {
171482872ac0SJason Evans 		ret = EFAULT;
171582872ac0SJason Evans 		goto label_return;
171682872ac0SJason Evans 	}
171782872ac0SJason Evans 
1718d0e79aa3SJason Evans 	if (oldp != NULL && oldlenp != NULL) {
17191f0a49e8SJason Evans 		size_t oldval = arena_lg_dirty_mult_get(tsd_tsdn(tsd), arena);
1720d0e79aa3SJason Evans 		READ(oldval, ssize_t);
1721d0e79aa3SJason Evans 	}
1722d0e79aa3SJason Evans 	if (newp != NULL) {
1723d0e79aa3SJason Evans 		if (newlen != sizeof(ssize_t)) {
1724d0e79aa3SJason Evans 			ret = EINVAL;
1725d0e79aa3SJason Evans 			goto label_return;
1726d0e79aa3SJason Evans 		}
17271f0a49e8SJason Evans 		if (arena_lg_dirty_mult_set(tsd_tsdn(tsd), arena,
17281f0a49e8SJason Evans 		    *(ssize_t *)newp)) {
1729d0e79aa3SJason Evans 			ret = EFAULT;
1730d0e79aa3SJason Evans 			goto label_return;
1731d0e79aa3SJason Evans 		}
1732d0e79aa3SJason Evans 	}
1733d0e79aa3SJason Evans 
1734d0e79aa3SJason Evans 	ret = 0;
1735d0e79aa3SJason Evans label_return:
1736d0e79aa3SJason Evans 	return (ret);
1737d0e79aa3SJason Evans }
1738d0e79aa3SJason Evans 
1739d0e79aa3SJason Evans static int
17401f0a49e8SJason Evans arena_i_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1741df0d881dSJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1742df0d881dSJason Evans {
1743df0d881dSJason Evans 	int ret;
1744df0d881dSJason Evans 	unsigned arena_ind = (unsigned)mib[1];
1745df0d881dSJason Evans 	arena_t *arena;
1746df0d881dSJason Evans 
17471f0a49e8SJason Evans 	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1748df0d881dSJason Evans 	if (arena == NULL) {
1749df0d881dSJason Evans 		ret = EFAULT;
1750df0d881dSJason Evans 		goto label_return;
1751df0d881dSJason Evans 	}
1752df0d881dSJason Evans 
1753df0d881dSJason Evans 	if (oldp != NULL && oldlenp != NULL) {
17541f0a49e8SJason Evans 		size_t oldval = arena_decay_time_get(tsd_tsdn(tsd), arena);
1755df0d881dSJason Evans 		READ(oldval, ssize_t);
1756df0d881dSJason Evans 	}
1757df0d881dSJason Evans 	if (newp != NULL) {
1758df0d881dSJason Evans 		if (newlen != sizeof(ssize_t)) {
1759df0d881dSJason Evans 			ret = EINVAL;
1760df0d881dSJason Evans 			goto label_return;
1761df0d881dSJason Evans 		}
17621f0a49e8SJason Evans 		if (arena_decay_time_set(tsd_tsdn(tsd), arena,
17631f0a49e8SJason Evans 		    *(ssize_t *)newp)) {
1764df0d881dSJason Evans 			ret = EFAULT;
1765df0d881dSJason Evans 			goto label_return;
1766df0d881dSJason Evans 		}
1767df0d881dSJason Evans 	}
1768df0d881dSJason Evans 
1769df0d881dSJason Evans 	ret = 0;
1770df0d881dSJason Evans label_return:
1771df0d881dSJason Evans 	return (ret);
1772df0d881dSJason Evans }
1773df0d881dSJason Evans 
1774df0d881dSJason Evans static int
17751f0a49e8SJason Evans arena_i_chunk_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
17761f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1777d0e79aa3SJason Evans {
1778d0e79aa3SJason Evans 	int ret;
1779df0d881dSJason Evans 	unsigned arena_ind = (unsigned)mib[1];
1780d0e79aa3SJason Evans 	arena_t *arena;
1781d0e79aa3SJason Evans 
17821f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1783d0e79aa3SJason Evans 	if (arena_ind < narenas_total_get() && (arena =
17841f0a49e8SJason Evans 	    arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) {
1785d0e79aa3SJason Evans 		if (newp != NULL) {
1786d0e79aa3SJason Evans 			chunk_hooks_t old_chunk_hooks, new_chunk_hooks;
1787d0e79aa3SJason Evans 			WRITE(new_chunk_hooks, chunk_hooks_t);
17881f0a49e8SJason Evans 			old_chunk_hooks = chunk_hooks_set(tsd_tsdn(tsd), arena,
1789d0e79aa3SJason Evans 			    &new_chunk_hooks);
1790d0e79aa3SJason Evans 			READ(old_chunk_hooks, chunk_hooks_t);
1791d0e79aa3SJason Evans 		} else {
17921f0a49e8SJason Evans 			chunk_hooks_t old_chunk_hooks =
17931f0a49e8SJason Evans 			    chunk_hooks_get(tsd_tsdn(tsd), arena);
1794d0e79aa3SJason Evans 			READ(old_chunk_hooks, chunk_hooks_t);
1795d0e79aa3SJason Evans 		}
1796d0e79aa3SJason Evans 	} else {
1797d0e79aa3SJason Evans 		ret = EFAULT;
1798d0e79aa3SJason Evans 		goto label_return;
1799d0e79aa3SJason Evans 	}
180082872ac0SJason Evans 	ret = 0;
180182872ac0SJason Evans label_return:
18021f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
180382872ac0SJason Evans 	return (ret);
180482872ac0SJason Evans }
180582872ac0SJason Evans 
180682872ac0SJason Evans static const ctl_named_node_t *
18071f0a49e8SJason Evans arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
180882872ac0SJason Evans {
180982872ac0SJason Evans 	const ctl_named_node_t *ret;
181082872ac0SJason Evans 
18111f0a49e8SJason Evans 	malloc_mutex_lock(tsdn, &ctl_mtx);
181282872ac0SJason Evans 	if (i > ctl_stats.narenas) {
181382872ac0SJason Evans 		ret = NULL;
181482872ac0SJason Evans 		goto label_return;
181582872ac0SJason Evans 	}
181682872ac0SJason Evans 
181782872ac0SJason Evans 	ret = super_arena_i_node;
181882872ac0SJason Evans label_return:
18191f0a49e8SJason Evans 	malloc_mutex_unlock(tsdn, &ctl_mtx);
182082872ac0SJason Evans 	return (ret);
182182872ac0SJason Evans }
182282872ac0SJason Evans 
182382872ac0SJason Evans /******************************************************************************/
182482872ac0SJason Evans 
182582872ac0SJason Evans static int
18261f0a49e8SJason Evans arenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
182782872ac0SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
182882872ac0SJason Evans {
182982872ac0SJason Evans 	int ret;
183082872ac0SJason Evans 	unsigned narenas;
183182872ac0SJason Evans 
18321f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
183382872ac0SJason Evans 	READONLY();
183482872ac0SJason Evans 	if (*oldlenp != sizeof(unsigned)) {
183582872ac0SJason Evans 		ret = EINVAL;
183682872ac0SJason Evans 		goto label_return;
183782872ac0SJason Evans 	}
183882872ac0SJason Evans 	narenas = ctl_stats.narenas;
183982872ac0SJason Evans 	READ(narenas, unsigned);
184082872ac0SJason Evans 
184182872ac0SJason Evans 	ret = 0;
184282872ac0SJason Evans label_return:
18431f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
184482872ac0SJason Evans 	return (ret);
184582872ac0SJason Evans }
1846a4bd5210SJason Evans 
1847a4bd5210SJason Evans static int
18481f0a49e8SJason Evans arenas_initialized_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1849a4bd5210SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1850a4bd5210SJason Evans {
1851a4bd5210SJason Evans 	int ret;
1852a4bd5210SJason Evans 	unsigned nread, i;
1853a4bd5210SJason Evans 
18541f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1855a4bd5210SJason Evans 	READONLY();
185682872ac0SJason Evans 	if (*oldlenp != ctl_stats.narenas * sizeof(bool)) {
1857a4bd5210SJason Evans 		ret = EINVAL;
185882872ac0SJason Evans 		nread = (*oldlenp < ctl_stats.narenas * sizeof(bool))
1859df0d881dSJason Evans 		    ? (unsigned)(*oldlenp / sizeof(bool)) : ctl_stats.narenas;
1860a4bd5210SJason Evans 	} else {
1861a4bd5210SJason Evans 		ret = 0;
186282872ac0SJason Evans 		nread = ctl_stats.narenas;
1863a4bd5210SJason Evans 	}
1864a4bd5210SJason Evans 
1865a4bd5210SJason Evans 	for (i = 0; i < nread; i++)
1866a4bd5210SJason Evans 		((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
1867a4bd5210SJason Evans 
1868a4bd5210SJason Evans label_return:
18691f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1870a4bd5210SJason Evans 	return (ret);
1871a4bd5210SJason Evans }
1872a4bd5210SJason Evans 
1873d0e79aa3SJason Evans static int
18741f0a49e8SJason Evans arenas_lg_dirty_mult_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
18751f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1876d0e79aa3SJason Evans {
1877d0e79aa3SJason Evans 	int ret;
1878d0e79aa3SJason Evans 
1879d0e79aa3SJason Evans 	if (oldp != NULL && oldlenp != NULL) {
1880d0e79aa3SJason Evans 		size_t oldval = arena_lg_dirty_mult_default_get();
1881d0e79aa3SJason Evans 		READ(oldval, ssize_t);
1882d0e79aa3SJason Evans 	}
1883d0e79aa3SJason Evans 	if (newp != NULL) {
1884d0e79aa3SJason Evans 		if (newlen != sizeof(ssize_t)) {
1885d0e79aa3SJason Evans 			ret = EINVAL;
1886d0e79aa3SJason Evans 			goto label_return;
1887d0e79aa3SJason Evans 		}
1888d0e79aa3SJason Evans 		if (arena_lg_dirty_mult_default_set(*(ssize_t *)newp)) {
1889d0e79aa3SJason Evans 			ret = EFAULT;
1890d0e79aa3SJason Evans 			goto label_return;
1891d0e79aa3SJason Evans 		}
1892d0e79aa3SJason Evans 	}
1893d0e79aa3SJason Evans 
1894d0e79aa3SJason Evans 	ret = 0;
1895d0e79aa3SJason Evans label_return:
1896d0e79aa3SJason Evans 	return (ret);
1897d0e79aa3SJason Evans }
1898d0e79aa3SJason Evans 
1899df0d881dSJason Evans static int
19001f0a49e8SJason Evans arenas_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1901df0d881dSJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1902df0d881dSJason Evans {
1903df0d881dSJason Evans 	int ret;
1904df0d881dSJason Evans 
1905df0d881dSJason Evans 	if (oldp != NULL && oldlenp != NULL) {
1906df0d881dSJason Evans 		size_t oldval = arena_decay_time_default_get();
1907df0d881dSJason Evans 		READ(oldval, ssize_t);
1908df0d881dSJason Evans 	}
1909df0d881dSJason Evans 	if (newp != NULL) {
1910df0d881dSJason Evans 		if (newlen != sizeof(ssize_t)) {
1911df0d881dSJason Evans 			ret = EINVAL;
1912df0d881dSJason Evans 			goto label_return;
1913df0d881dSJason Evans 		}
1914df0d881dSJason Evans 		if (arena_decay_time_default_set(*(ssize_t *)newp)) {
1915df0d881dSJason Evans 			ret = EFAULT;
1916df0d881dSJason Evans 			goto label_return;
1917df0d881dSJason Evans 		}
1918df0d881dSJason Evans 	}
1919df0d881dSJason Evans 
1920df0d881dSJason Evans 	ret = 0;
1921df0d881dSJason Evans label_return:
1922df0d881dSJason Evans 	return (ret);
1923df0d881dSJason Evans }
1924df0d881dSJason Evans 
1925a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
1926a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_page, PAGE, size_t)
1927a4bd5210SJason Evans CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)
1928a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)
1929a4bd5210SJason Evans CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)
1930f921d10fSJason Evans CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)
1931f921d10fSJason Evans CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)
1932f921d10fSJason Evans CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)
1933f921d10fSJason Evans static const ctl_named_node_t *
19341f0a49e8SJason Evans arenas_bin_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1935f921d10fSJason Evans {
1936f921d10fSJason Evans 
1937f921d10fSJason Evans 	if (i > NBINS)
1938f921d10fSJason Evans 		return (NULL);
1939f921d10fSJason Evans 	return (super_arenas_bin_i_node);
1940f921d10fSJason Evans }
1941f921d10fSJason Evans 
1942d0e79aa3SJason Evans CTL_RO_NL_GEN(arenas_nlruns, nlclasses, unsigned)
1943df0d881dSJason Evans CTL_RO_NL_GEN(arenas_lrun_i_size, index2size(NBINS+(szind_t)mib[2]), size_t)
1944f921d10fSJason Evans static const ctl_named_node_t *
19451f0a49e8SJason Evans arenas_lrun_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1946f921d10fSJason Evans {
1947f921d10fSJason Evans 
1948f921d10fSJason Evans 	if (i > nlclasses)
1949f921d10fSJason Evans 		return (NULL);
1950f921d10fSJason Evans 	return (super_arenas_lrun_i_node);
1951f921d10fSJason Evans }
1952a4bd5210SJason Evans 
1953d0e79aa3SJason Evans CTL_RO_NL_GEN(arenas_nhchunks, nhclasses, unsigned)
1954df0d881dSJason Evans CTL_RO_NL_GEN(arenas_hchunk_i_size, index2size(NBINS+nlclasses+(szind_t)mib[2]),
1955df0d881dSJason Evans     size_t)
1956d0e79aa3SJason Evans static const ctl_named_node_t *
19571f0a49e8SJason Evans arenas_hchunk_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1958a4bd5210SJason Evans {
1959a4bd5210SJason Evans 
1960d0e79aa3SJason Evans 	if (i > nhclasses)
1961d0e79aa3SJason Evans 		return (NULL);
1962d0e79aa3SJason Evans 	return (super_arenas_hchunk_i_node);
196382872ac0SJason Evans }
196482872ac0SJason Evans 
196582872ac0SJason Evans static int
19661f0a49e8SJason Evans arenas_extend_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
19671f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
196882872ac0SJason Evans {
196982872ac0SJason Evans 	int ret;
197088ad2f8dSJason Evans 	unsigned narenas;
197182872ac0SJason Evans 
19721f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
197382872ac0SJason Evans 	READONLY();
19741f0a49e8SJason Evans 	if (ctl_grow(tsd_tsdn(tsd))) {
197582872ac0SJason Evans 		ret = EAGAIN;
1976a4bd5210SJason Evans 		goto label_return;
1977a4bd5210SJason Evans 	}
197888ad2f8dSJason Evans 	narenas = ctl_stats.narenas - 1;
197988ad2f8dSJason Evans 	READ(narenas, unsigned);
1980a4bd5210SJason Evans 
1981a4bd5210SJason Evans 	ret = 0;
1982a4bd5210SJason Evans label_return:
19831f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1984a4bd5210SJason Evans 	return (ret);
1985a4bd5210SJason Evans }
1986a4bd5210SJason Evans 
1987a4bd5210SJason Evans /******************************************************************************/
1988a4bd5210SJason Evans 
1989a4bd5210SJason Evans static int
19901f0a49e8SJason Evans prof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
19911f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
19921f0a49e8SJason Evans {
19931f0a49e8SJason Evans 	int ret;
19941f0a49e8SJason Evans 	bool oldval;
19951f0a49e8SJason Evans 
19961f0a49e8SJason Evans 	if (!config_prof)
19971f0a49e8SJason Evans 		return (ENOENT);
19981f0a49e8SJason Evans 
19991f0a49e8SJason Evans 	if (newp != NULL) {
20001f0a49e8SJason Evans 		if (newlen != sizeof(bool)) {
20011f0a49e8SJason Evans 			ret = EINVAL;
20021f0a49e8SJason Evans 			goto label_return;
20031f0a49e8SJason Evans 		}
20041f0a49e8SJason Evans 		oldval = prof_thread_active_init_set(tsd_tsdn(tsd),
20051f0a49e8SJason Evans 		    *(bool *)newp);
20061f0a49e8SJason Evans 	} else
20071f0a49e8SJason Evans 		oldval = prof_thread_active_init_get(tsd_tsdn(tsd));
20081f0a49e8SJason Evans 	READ(oldval, bool);
20091f0a49e8SJason Evans 
20101f0a49e8SJason Evans 	ret = 0;
20111f0a49e8SJason Evans label_return:
20121f0a49e8SJason Evans 	return (ret);
20131f0a49e8SJason Evans }
20141f0a49e8SJason Evans 
20151f0a49e8SJason Evans static int
20161f0a49e8SJason Evans prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2017d0e79aa3SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
2018d0e79aa3SJason Evans {
2019d0e79aa3SJason Evans 	int ret;
2020d0e79aa3SJason Evans 	bool oldval;
2021d0e79aa3SJason Evans 
2022d0e79aa3SJason Evans 	if (!config_prof)
2023d0e79aa3SJason Evans 		return (ENOENT);
2024d0e79aa3SJason Evans 
2025d0e79aa3SJason Evans 	if (newp != NULL) {
2026d0e79aa3SJason Evans 		if (newlen != sizeof(bool)) {
2027d0e79aa3SJason Evans 			ret = EINVAL;
2028d0e79aa3SJason Evans 			goto label_return;
2029d0e79aa3SJason Evans 		}
20301f0a49e8SJason Evans 		oldval = prof_active_set(tsd_tsdn(tsd), *(bool *)newp);
2031d0e79aa3SJason Evans 	} else
20321f0a49e8SJason Evans 		oldval = prof_active_get(tsd_tsdn(tsd));
2033d0e79aa3SJason Evans 	READ(oldval, bool);
2034d0e79aa3SJason Evans 
2035d0e79aa3SJason Evans 	ret = 0;
2036d0e79aa3SJason Evans label_return:
2037d0e79aa3SJason Evans 	return (ret);
2038d0e79aa3SJason Evans }
2039d0e79aa3SJason Evans 
2040d0e79aa3SJason Evans static int
20411f0a49e8SJason Evans prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
20421f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
2043a4bd5210SJason Evans {
2044a4bd5210SJason Evans 	int ret;
2045a4bd5210SJason Evans 	const char *filename = NULL;
2046a4bd5210SJason Evans 
2047d0e79aa3SJason Evans 	if (!config_prof)
2048a4bd5210SJason Evans 		return (ENOENT);
2049a4bd5210SJason Evans 
2050a4bd5210SJason Evans 	WRITEONLY();
2051a4bd5210SJason Evans 	WRITE(filename, const char *);
2052a4bd5210SJason Evans 
20531f0a49e8SJason Evans 	if (prof_mdump(tsd, filename)) {
2054a4bd5210SJason Evans 		ret = EFAULT;
2055a4bd5210SJason Evans 		goto label_return;
2056a4bd5210SJason Evans 	}
2057a4bd5210SJason Evans 
2058a4bd5210SJason Evans 	ret = 0;
2059a4bd5210SJason Evans label_return:
2060a4bd5210SJason Evans 	return (ret);
2061a4bd5210SJason Evans }
2062a4bd5210SJason Evans 
2063d0e79aa3SJason Evans static int
20641f0a49e8SJason Evans prof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
20651f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
2066d0e79aa3SJason Evans {
2067d0e79aa3SJason Evans 	int ret;
2068d0e79aa3SJason Evans 	bool oldval;
2069d0e79aa3SJason Evans 
2070d0e79aa3SJason Evans 	if (!config_prof)
2071d0e79aa3SJason Evans 		return (ENOENT);
2072d0e79aa3SJason Evans 
2073d0e79aa3SJason Evans 	if (newp != NULL) {
2074d0e79aa3SJason Evans 		if (newlen != sizeof(bool)) {
2075d0e79aa3SJason Evans 			ret = EINVAL;
2076d0e79aa3SJason Evans 			goto label_return;
2077d0e79aa3SJason Evans 		}
20781f0a49e8SJason Evans 		oldval = prof_gdump_set(tsd_tsdn(tsd), *(bool *)newp);
2079d0e79aa3SJason Evans 	} else
20801f0a49e8SJason Evans 		oldval = prof_gdump_get(tsd_tsdn(tsd));
2081d0e79aa3SJason Evans 	READ(oldval, bool);
2082d0e79aa3SJason Evans 
2083d0e79aa3SJason Evans 	ret = 0;
2084d0e79aa3SJason Evans label_return:
2085d0e79aa3SJason Evans 	return (ret);
2086d0e79aa3SJason Evans }
2087d0e79aa3SJason Evans 
2088d0e79aa3SJason Evans static int
20891f0a49e8SJason Evans prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
20901f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
2091d0e79aa3SJason Evans {
2092d0e79aa3SJason Evans 	int ret;
2093d0e79aa3SJason Evans 	size_t lg_sample = lg_prof_sample;
2094d0e79aa3SJason Evans 
2095d0e79aa3SJason Evans 	if (!config_prof)
2096d0e79aa3SJason Evans 		return (ENOENT);
2097d0e79aa3SJason Evans 
2098d0e79aa3SJason Evans 	WRITEONLY();
2099d0e79aa3SJason Evans 	WRITE(lg_sample, size_t);
2100d0e79aa3SJason Evans 	if (lg_sample >= (sizeof(uint64_t) << 3))
2101d0e79aa3SJason Evans 		lg_sample = (sizeof(uint64_t) << 3) - 1;
2102d0e79aa3SJason Evans 
2103*bde95144SJason Evans 	prof_reset(tsd, lg_sample);
2104d0e79aa3SJason Evans 
2105d0e79aa3SJason Evans 	ret = 0;
2106d0e79aa3SJason Evans label_return:
2107d0e79aa3SJason Evans 	return (ret);
2108d0e79aa3SJason Evans }
2109d0e79aa3SJason Evans 
2110a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
2111d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t)
2112a4bd5210SJason Evans 
2113a4bd5210SJason Evans /******************************************************************************/
2114a4bd5210SJason Evans 
2115f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)
2116f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)
2117f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
2118d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_metadata, ctl_stats.metadata, size_t)
2119d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_resident, ctl_stats.resident, size_t)
2120f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)
21211f0a49e8SJason Evans CTL_RO_CGEN(config_stats, stats_retained, ctl_stats.retained, size_t)
2122f921d10fSJason Evans 
2123f921d10fSJason Evans CTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)
2124d0e79aa3SJason Evans CTL_RO_GEN(stats_arenas_i_lg_dirty_mult, ctl_stats.arenas[mib[2]].lg_dirty_mult,
2125d0e79aa3SJason Evans     ssize_t)
2126df0d881dSJason Evans CTL_RO_GEN(stats_arenas_i_decay_time, ctl_stats.arenas[mib[2]].decay_time,
2127df0d881dSJason Evans     ssize_t)
2128f921d10fSJason Evans CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)
2129f921d10fSJason Evans CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
2130f921d10fSJason Evans CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
2131f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
2132f921d10fSJason Evans     ctl_stats.arenas[mib[2]].astats.mapped, size_t)
21331f0a49e8SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_retained,
21341f0a49e8SJason Evans     ctl_stats.arenas[mib[2]].astats.retained, size_t)
2135f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
2136f921d10fSJason Evans     ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
2137f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
2138f921d10fSJason Evans     ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)
2139f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_purged,
2140f921d10fSJason Evans     ctl_stats.arenas[mib[2]].astats.purged, uint64_t)
2141d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_mapped,
2142d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.metadata_mapped, size_t)
2143d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_allocated,
2144d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.metadata_allocated, size_t)
2145f921d10fSJason Evans 
2146a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
2147a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].allocated_small, size_t)
2148a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
2149a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)
2150a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
2151a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)
2152a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
2153a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)
2154a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
2155a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)
2156a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
2157a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)
2158a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
2159a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)
2160a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
2161a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)
2162d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_huge_allocated,
2163d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.allocated_huge, size_t)
2164d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_huge_nmalloc,
2165d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t)
2166d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_huge_ndalloc,
2167d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.ndalloc_huge, uint64_t)
2168d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_huge_nrequests,
2169d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t) /* Intentional. */
2170a4bd5210SJason Evans 
2171a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
2172a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)
2173a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
2174a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)
2175a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
2176a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)
2177d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curregs,
2178d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].curregs, size_t)
2179a4bd5210SJason Evans CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,
2180a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)
2181a4bd5210SJason Evans CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,
2182a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)
2183a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,
2184a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)
2185a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,
2186a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)
2187a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,
2188a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)
2189a4bd5210SJason Evans 
219082872ac0SJason Evans static const ctl_named_node_t *
21911f0a49e8SJason Evans stats_arenas_i_bins_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
21921f0a49e8SJason Evans     size_t j)
2193a4bd5210SJason Evans {
2194a4bd5210SJason Evans 
2195a4bd5210SJason Evans 	if (j > NBINS)
2196a4bd5210SJason Evans 		return (NULL);
2197a4bd5210SJason Evans 	return (super_stats_arenas_i_bins_j_node);
2198a4bd5210SJason Evans }
2199a4bd5210SJason Evans 
2200a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,
2201a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)
2202a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,
2203a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)
2204a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,
2205a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)
2206a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,
2207a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)
2208a4bd5210SJason Evans 
220982872ac0SJason Evans static const ctl_named_node_t *
22101f0a49e8SJason Evans stats_arenas_i_lruns_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
22111f0a49e8SJason Evans     size_t j)
2212a4bd5210SJason Evans {
2213a4bd5210SJason Evans 
2214a4bd5210SJason Evans 	if (j > nlclasses)
2215a4bd5210SJason Evans 		return (NULL);
2216a4bd5210SJason Evans 	return (super_stats_arenas_i_lruns_j_node);
2217a4bd5210SJason Evans }
2218a4bd5210SJason Evans 
2219d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nmalloc,
2220d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, uint64_t)
2221d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_ndalloc,
2222d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].hstats[mib[4]].ndalloc, uint64_t)
2223d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nrequests,
2224d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, /* Intentional. */
2225d0e79aa3SJason Evans     uint64_t)
2226d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_curhchunks,
2227d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].hstats[mib[4]].curhchunks, size_t)
2228d0e79aa3SJason Evans 
2229d0e79aa3SJason Evans static const ctl_named_node_t *
22301f0a49e8SJason Evans stats_arenas_i_hchunks_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
22311f0a49e8SJason Evans     size_t j)
2232d0e79aa3SJason Evans {
2233d0e79aa3SJason Evans 
2234d0e79aa3SJason Evans 	if (j > nhclasses)
2235d0e79aa3SJason Evans 		return (NULL);
2236d0e79aa3SJason Evans 	return (super_stats_arenas_i_hchunks_j_node);
2237d0e79aa3SJason Evans }
2238d0e79aa3SJason Evans 
223982872ac0SJason Evans static const ctl_named_node_t *
22401f0a49e8SJason Evans stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
2241a4bd5210SJason Evans {
2242e722f8f8SJason Evans 	const ctl_named_node_t * ret;
2243a4bd5210SJason Evans 
22441f0a49e8SJason Evans 	malloc_mutex_lock(tsdn, &ctl_mtx);
2245d0e79aa3SJason Evans 	if (i > ctl_stats.narenas || !ctl_stats.arenas[i].initialized) {
2246a4bd5210SJason Evans 		ret = NULL;
2247a4bd5210SJason Evans 		goto label_return;
2248a4bd5210SJason Evans 	}
2249a4bd5210SJason Evans 
2250a4bd5210SJason Evans 	ret = super_stats_arenas_i_node;
2251a4bd5210SJason Evans label_return:
22521f0a49e8SJason Evans 	malloc_mutex_unlock(tsdn, &ctl_mtx);
2253a4bd5210SJason Evans 	return (ret);
2254a4bd5210SJason Evans }
2255