xref: /freebsd/contrib/jemalloc/src/ctl.c (revision 8244f2aa7cb3ce15f2d5ce7f860913d2e7cc784d)
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)
87*8244f2aaSJason Evans CTL_PROTO(config_thp)
88a4bd5210SJason Evans CTL_PROTO(config_tls)
89a4bd5210SJason Evans CTL_PROTO(config_utrace)
90a4bd5210SJason Evans CTL_PROTO(config_valgrind)
91a4bd5210SJason Evans CTL_PROTO(config_xmalloc)
92a4bd5210SJason Evans CTL_PROTO(opt_abort)
9382872ac0SJason Evans CTL_PROTO(opt_dss)
94a4bd5210SJason Evans CTL_PROTO(opt_lg_chunk)
95a4bd5210SJason Evans CTL_PROTO(opt_narenas)
96df0d881dSJason Evans CTL_PROTO(opt_purge)
97a4bd5210SJason Evans CTL_PROTO(opt_lg_dirty_mult)
98df0d881dSJason Evans CTL_PROTO(opt_decay_time)
99a4bd5210SJason Evans CTL_PROTO(opt_stats_print)
100a4bd5210SJason Evans CTL_PROTO(opt_junk)
101a4bd5210SJason Evans CTL_PROTO(opt_zero)
102a4bd5210SJason Evans CTL_PROTO(opt_quarantine)
103a4bd5210SJason Evans CTL_PROTO(opt_redzone)
104a4bd5210SJason Evans CTL_PROTO(opt_utrace)
105a4bd5210SJason Evans CTL_PROTO(opt_xmalloc)
106a4bd5210SJason Evans CTL_PROTO(opt_tcache)
107a4bd5210SJason Evans CTL_PROTO(opt_lg_tcache_max)
108*8244f2aaSJason Evans CTL_PROTO(opt_thp)
109a4bd5210SJason Evans CTL_PROTO(opt_prof)
110a4bd5210SJason Evans CTL_PROTO(opt_prof_prefix)
111a4bd5210SJason Evans CTL_PROTO(opt_prof_active)
112d0e79aa3SJason Evans CTL_PROTO(opt_prof_thread_active_init)
113a4bd5210SJason Evans CTL_PROTO(opt_lg_prof_sample)
114a4bd5210SJason Evans CTL_PROTO(opt_lg_prof_interval)
115a4bd5210SJason Evans CTL_PROTO(opt_prof_gdump)
1168ed34ab0SJason Evans CTL_PROTO(opt_prof_final)
117a4bd5210SJason Evans CTL_PROTO(opt_prof_leak)
118a4bd5210SJason Evans CTL_PROTO(opt_prof_accum)
119d0e79aa3SJason Evans CTL_PROTO(tcache_create)
120d0e79aa3SJason Evans CTL_PROTO(tcache_flush)
121d0e79aa3SJason Evans CTL_PROTO(tcache_destroy)
1221f0a49e8SJason Evans static void	arena_i_purge(tsdn_t *tsdn, unsigned arena_ind, bool all);
12382872ac0SJason Evans CTL_PROTO(arena_i_purge)
124df0d881dSJason Evans CTL_PROTO(arena_i_decay)
1251f0a49e8SJason Evans CTL_PROTO(arena_i_reset)
12682872ac0SJason Evans CTL_PROTO(arena_i_dss)
127d0e79aa3SJason Evans CTL_PROTO(arena_i_lg_dirty_mult)
128df0d881dSJason Evans CTL_PROTO(arena_i_decay_time)
129d0e79aa3SJason Evans CTL_PROTO(arena_i_chunk_hooks)
13082872ac0SJason Evans INDEX_PROTO(arena_i)
131a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_size)
132a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_nregs)
133a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_run_size)
134a4bd5210SJason Evans INDEX_PROTO(arenas_bin_i)
135a4bd5210SJason Evans CTL_PROTO(arenas_lrun_i_size)
136a4bd5210SJason Evans INDEX_PROTO(arenas_lrun_i)
137d0e79aa3SJason Evans CTL_PROTO(arenas_hchunk_i_size)
138d0e79aa3SJason Evans INDEX_PROTO(arenas_hchunk_i)
139a4bd5210SJason Evans CTL_PROTO(arenas_narenas)
140a4bd5210SJason Evans CTL_PROTO(arenas_initialized)
141d0e79aa3SJason Evans CTL_PROTO(arenas_lg_dirty_mult)
142df0d881dSJason Evans CTL_PROTO(arenas_decay_time)
143a4bd5210SJason Evans CTL_PROTO(arenas_quantum)
144a4bd5210SJason Evans CTL_PROTO(arenas_page)
145a4bd5210SJason Evans CTL_PROTO(arenas_tcache_max)
146a4bd5210SJason Evans CTL_PROTO(arenas_nbins)
147a4bd5210SJason Evans CTL_PROTO(arenas_nhbins)
148a4bd5210SJason Evans CTL_PROTO(arenas_nlruns)
149d0e79aa3SJason Evans CTL_PROTO(arenas_nhchunks)
15082872ac0SJason Evans CTL_PROTO(arenas_extend)
151d0e79aa3SJason Evans CTL_PROTO(prof_thread_active_init)
152a4bd5210SJason Evans CTL_PROTO(prof_active)
153a4bd5210SJason Evans CTL_PROTO(prof_dump)
154d0e79aa3SJason Evans CTL_PROTO(prof_gdump)
155d0e79aa3SJason Evans CTL_PROTO(prof_reset)
156a4bd5210SJason Evans CTL_PROTO(prof_interval)
157d0e79aa3SJason Evans CTL_PROTO(lg_prof_sample)
158a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_allocated)
159a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_nmalloc)
160a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_ndalloc)
161a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_nrequests)
162a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_allocated)
163a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_nmalloc)
164a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_ndalloc)
165a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_large_nrequests)
166d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_huge_allocated)
167d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_huge_nmalloc)
168d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_huge_ndalloc)
169d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_huge_nrequests)
170a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nmalloc)
171a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_ndalloc)
172a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nrequests)
173d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_bins_j_curregs)
174a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nfills)
175a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nflushes)
176a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nruns)
177a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nreruns)
178a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_curruns)
179a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i_bins_j)
180a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_nmalloc)
181a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_ndalloc)
182a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_nrequests)
183a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_lruns_j_curruns)
184a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i_lruns_j)
185d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_hchunks_j_nmalloc)
186d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_hchunks_j_ndalloc)
187d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_hchunks_j_nrequests)
188d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_hchunks_j_curhchunks)
189d0e79aa3SJason Evans INDEX_PROTO(stats_arenas_i_hchunks_j)
190a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_nthreads)
19182872ac0SJason Evans CTL_PROTO(stats_arenas_i_dss)
192d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_lg_dirty_mult)
193df0d881dSJason Evans CTL_PROTO(stats_arenas_i_decay_time)
194a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_pactive)
195a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_pdirty)
196a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_mapped)
1971f0a49e8SJason Evans CTL_PROTO(stats_arenas_i_retained)
198a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_npurge)
199a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_nmadvise)
200a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_purged)
201d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_metadata_mapped)
202d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_metadata_allocated)
203a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i)
204a4bd5210SJason Evans CTL_PROTO(stats_cactive)
205a4bd5210SJason Evans CTL_PROTO(stats_allocated)
206a4bd5210SJason Evans CTL_PROTO(stats_active)
207d0e79aa3SJason Evans CTL_PROTO(stats_metadata)
208d0e79aa3SJason Evans CTL_PROTO(stats_resident)
209a4bd5210SJason Evans CTL_PROTO(stats_mapped)
2101f0a49e8SJason Evans CTL_PROTO(stats_retained)
211a4bd5210SJason Evans 
212a4bd5210SJason Evans /******************************************************************************/
213a4bd5210SJason Evans /* mallctl tree. */
214a4bd5210SJason Evans 
215a4bd5210SJason Evans /* Maximum tree depth. */
216a4bd5210SJason Evans #define	CTL_MAX_DEPTH	6
217a4bd5210SJason Evans 
218e722f8f8SJason Evans #define	NAME(n)	{true},	n
219e722f8f8SJason Evans #define	CHILD(t, c)							\
220e722f8f8SJason Evans 	sizeof(c##_node) / sizeof(ctl_##t##_node_t),			\
221e722f8f8SJason Evans 	(ctl_node_t *)c##_node,						\
222e722f8f8SJason Evans 	NULL
223e722f8f8SJason Evans #define	CTL(c)	0, NULL, c##_ctl
224a4bd5210SJason Evans 
225a4bd5210SJason Evans /*
226a4bd5210SJason Evans  * Only handles internal indexed nodes, since there are currently no external
227a4bd5210SJason Evans  * ones.
228a4bd5210SJason Evans  */
229e722f8f8SJason Evans #define	INDEX(i)	{false},	i##_index
230a4bd5210SJason Evans 
231d0e79aa3SJason Evans static const ctl_named_node_t	thread_tcache_node[] = {
232a4bd5210SJason Evans 	{NAME("enabled"),	CTL(thread_tcache_enabled)},
233a4bd5210SJason Evans 	{NAME("flush"),		CTL(thread_tcache_flush)}
234a4bd5210SJason Evans };
235a4bd5210SJason Evans 
236d0e79aa3SJason Evans static const ctl_named_node_t	thread_prof_node[] = {
237d0e79aa3SJason Evans 	{NAME("name"),		CTL(thread_prof_name)},
238d0e79aa3SJason Evans 	{NAME("active"),	CTL(thread_prof_active)}
239d0e79aa3SJason Evans };
240d0e79aa3SJason Evans 
241e722f8f8SJason Evans static const ctl_named_node_t	thread_node[] = {
242a4bd5210SJason Evans 	{NAME("arena"),		CTL(thread_arena)},
243a4bd5210SJason Evans 	{NAME("allocated"),	CTL(thread_allocated)},
244a4bd5210SJason Evans 	{NAME("allocatedp"),	CTL(thread_allocatedp)},
245a4bd5210SJason Evans 	{NAME("deallocated"),	CTL(thread_deallocated)},
246a4bd5210SJason Evans 	{NAME("deallocatedp"),	CTL(thread_deallocatedp)},
247d0e79aa3SJason Evans 	{NAME("tcache"),	CHILD(named, thread_tcache)},
248d0e79aa3SJason Evans 	{NAME("prof"),		CHILD(named, thread_prof)}
249a4bd5210SJason Evans };
250a4bd5210SJason Evans 
251e722f8f8SJason Evans static const ctl_named_node_t	config_node[] = {
252d0e79aa3SJason Evans 	{NAME("cache_oblivious"), CTL(config_cache_oblivious)},
253a4bd5210SJason Evans 	{NAME("debug"),		CTL(config_debug)},
254a4bd5210SJason Evans 	{NAME("fill"),		CTL(config_fill)},
255a4bd5210SJason Evans 	{NAME("lazy_lock"),	CTL(config_lazy_lock)},
256df0d881dSJason Evans 	{NAME("malloc_conf"),	CTL(config_malloc_conf)},
257a4bd5210SJason Evans 	{NAME("munmap"),	CTL(config_munmap)},
258a4bd5210SJason Evans 	{NAME("prof"),		CTL(config_prof)},
259a4bd5210SJason Evans 	{NAME("prof_libgcc"),	CTL(config_prof_libgcc)},
260a4bd5210SJason Evans 	{NAME("prof_libunwind"), CTL(config_prof_libunwind)},
261a4bd5210SJason Evans 	{NAME("stats"),		CTL(config_stats)},
262a4bd5210SJason Evans 	{NAME("tcache"),	CTL(config_tcache)},
263*8244f2aaSJason Evans 	{NAME("thp"),		CTL(config_thp)},
264a4bd5210SJason Evans 	{NAME("tls"),		CTL(config_tls)},
265a4bd5210SJason Evans 	{NAME("utrace"),	CTL(config_utrace)},
266a4bd5210SJason Evans 	{NAME("valgrind"),	CTL(config_valgrind)},
267a4bd5210SJason Evans 	{NAME("xmalloc"),	CTL(config_xmalloc)}
268a4bd5210SJason Evans };
269a4bd5210SJason Evans 
270e722f8f8SJason Evans static const ctl_named_node_t opt_node[] = {
271a4bd5210SJason Evans 	{NAME("abort"),		CTL(opt_abort)},
27282872ac0SJason Evans 	{NAME("dss"),		CTL(opt_dss)},
273a4bd5210SJason Evans 	{NAME("lg_chunk"),	CTL(opt_lg_chunk)},
274a4bd5210SJason Evans 	{NAME("narenas"),	CTL(opt_narenas)},
275df0d881dSJason Evans 	{NAME("purge"),		CTL(opt_purge)},
276a4bd5210SJason Evans 	{NAME("lg_dirty_mult"),	CTL(opt_lg_dirty_mult)},
277df0d881dSJason Evans 	{NAME("decay_time"),	CTL(opt_decay_time)},
278a4bd5210SJason Evans 	{NAME("stats_print"),	CTL(opt_stats_print)},
279a4bd5210SJason Evans 	{NAME("junk"),		CTL(opt_junk)},
280a4bd5210SJason Evans 	{NAME("zero"),		CTL(opt_zero)},
281a4bd5210SJason Evans 	{NAME("quarantine"),	CTL(opt_quarantine)},
282a4bd5210SJason Evans 	{NAME("redzone"),	CTL(opt_redzone)},
283a4bd5210SJason Evans 	{NAME("utrace"),	CTL(opt_utrace)},
284a4bd5210SJason Evans 	{NAME("xmalloc"),	CTL(opt_xmalloc)},
285a4bd5210SJason Evans 	{NAME("tcache"),	CTL(opt_tcache)},
286a4bd5210SJason Evans 	{NAME("lg_tcache_max"),	CTL(opt_lg_tcache_max)},
287*8244f2aaSJason Evans 	{NAME("thp"),		CTL(opt_thp)},
288a4bd5210SJason Evans 	{NAME("prof"),		CTL(opt_prof)},
289a4bd5210SJason Evans 	{NAME("prof_prefix"),	CTL(opt_prof_prefix)},
290a4bd5210SJason Evans 	{NAME("prof_active"),	CTL(opt_prof_active)},
291d0e79aa3SJason Evans 	{NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)},
292a4bd5210SJason Evans 	{NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
293a4bd5210SJason Evans 	{NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
294a4bd5210SJason Evans 	{NAME("prof_gdump"),	CTL(opt_prof_gdump)},
2958ed34ab0SJason Evans 	{NAME("prof_final"),	CTL(opt_prof_final)},
296a4bd5210SJason Evans 	{NAME("prof_leak"),	CTL(opt_prof_leak)},
297a4bd5210SJason Evans 	{NAME("prof_accum"),	CTL(opt_prof_accum)}
298a4bd5210SJason Evans };
299a4bd5210SJason Evans 
300d0e79aa3SJason Evans static const ctl_named_node_t	tcache_node[] = {
301d0e79aa3SJason Evans 	{NAME("create"),	CTL(tcache_create)},
302d0e79aa3SJason Evans 	{NAME("flush"),		CTL(tcache_flush)},
303d0e79aa3SJason Evans 	{NAME("destroy"),	CTL(tcache_destroy)}
304d0e79aa3SJason Evans };
305d0e79aa3SJason Evans 
30682872ac0SJason Evans static const ctl_named_node_t arena_i_node[] = {
30782872ac0SJason Evans 	{NAME("purge"),		CTL(arena_i_purge)},
308df0d881dSJason Evans 	{NAME("decay"),		CTL(arena_i_decay)},
3091f0a49e8SJason Evans 	{NAME("reset"),		CTL(arena_i_reset)},
310d0e79aa3SJason Evans 	{NAME("dss"),		CTL(arena_i_dss)},
311d0e79aa3SJason Evans 	{NAME("lg_dirty_mult"),	CTL(arena_i_lg_dirty_mult)},
312df0d881dSJason Evans 	{NAME("decay_time"),	CTL(arena_i_decay_time)},
313d0e79aa3SJason Evans 	{NAME("chunk_hooks"),	CTL(arena_i_chunk_hooks)}
31482872ac0SJason Evans };
31582872ac0SJason Evans static const ctl_named_node_t super_arena_i_node[] = {
31682872ac0SJason Evans 	{NAME(""),		CHILD(named, arena_i)}
31782872ac0SJason Evans };
31882872ac0SJason Evans 
31982872ac0SJason Evans static const ctl_indexed_node_t arena_node[] = {
32082872ac0SJason Evans 	{INDEX(arena_i)}
32182872ac0SJason Evans };
32282872ac0SJason Evans 
323e722f8f8SJason Evans static const ctl_named_node_t arenas_bin_i_node[] = {
324a4bd5210SJason Evans 	{NAME("size"),		CTL(arenas_bin_i_size)},
325a4bd5210SJason Evans 	{NAME("nregs"),		CTL(arenas_bin_i_nregs)},
326a4bd5210SJason Evans 	{NAME("run_size"),	CTL(arenas_bin_i_run_size)}
327a4bd5210SJason Evans };
328e722f8f8SJason Evans static const ctl_named_node_t super_arenas_bin_i_node[] = {
329e722f8f8SJason Evans 	{NAME(""),		CHILD(named, arenas_bin_i)}
330a4bd5210SJason Evans };
331a4bd5210SJason Evans 
332e722f8f8SJason Evans static const ctl_indexed_node_t arenas_bin_node[] = {
333a4bd5210SJason Evans 	{INDEX(arenas_bin_i)}
334a4bd5210SJason Evans };
335a4bd5210SJason Evans 
336e722f8f8SJason Evans static const ctl_named_node_t arenas_lrun_i_node[] = {
337a4bd5210SJason Evans 	{NAME("size"),		CTL(arenas_lrun_i_size)}
338a4bd5210SJason Evans };
339e722f8f8SJason Evans static const ctl_named_node_t super_arenas_lrun_i_node[] = {
340e722f8f8SJason Evans 	{NAME(""),		CHILD(named, arenas_lrun_i)}
341a4bd5210SJason Evans };
342a4bd5210SJason Evans 
343e722f8f8SJason Evans static const ctl_indexed_node_t arenas_lrun_node[] = {
344a4bd5210SJason Evans 	{INDEX(arenas_lrun_i)}
345a4bd5210SJason Evans };
346a4bd5210SJason Evans 
347d0e79aa3SJason Evans static const ctl_named_node_t arenas_hchunk_i_node[] = {
348d0e79aa3SJason Evans 	{NAME("size"),		CTL(arenas_hchunk_i_size)}
349d0e79aa3SJason Evans };
350d0e79aa3SJason Evans static const ctl_named_node_t super_arenas_hchunk_i_node[] = {
351d0e79aa3SJason Evans 	{NAME(""),		CHILD(named, arenas_hchunk_i)}
352d0e79aa3SJason Evans };
353d0e79aa3SJason Evans 
354d0e79aa3SJason Evans static const ctl_indexed_node_t arenas_hchunk_node[] = {
355d0e79aa3SJason Evans 	{INDEX(arenas_hchunk_i)}
356d0e79aa3SJason Evans };
357d0e79aa3SJason Evans 
358e722f8f8SJason Evans static const ctl_named_node_t arenas_node[] = {
359a4bd5210SJason Evans 	{NAME("narenas"),	CTL(arenas_narenas)},
360a4bd5210SJason Evans 	{NAME("initialized"),	CTL(arenas_initialized)},
361d0e79aa3SJason Evans 	{NAME("lg_dirty_mult"),	CTL(arenas_lg_dirty_mult)},
362df0d881dSJason Evans 	{NAME("decay_time"),	CTL(arenas_decay_time)},
363a4bd5210SJason Evans 	{NAME("quantum"),	CTL(arenas_quantum)},
364a4bd5210SJason Evans 	{NAME("page"),		CTL(arenas_page)},
365a4bd5210SJason Evans 	{NAME("tcache_max"),	CTL(arenas_tcache_max)},
366a4bd5210SJason Evans 	{NAME("nbins"),		CTL(arenas_nbins)},
367a4bd5210SJason Evans 	{NAME("nhbins"),	CTL(arenas_nhbins)},
368e722f8f8SJason Evans 	{NAME("bin"),		CHILD(indexed, arenas_bin)},
369a4bd5210SJason Evans 	{NAME("nlruns"),	CTL(arenas_nlruns)},
370e722f8f8SJason Evans 	{NAME("lrun"),		CHILD(indexed, arenas_lrun)},
371d0e79aa3SJason Evans 	{NAME("nhchunks"),	CTL(arenas_nhchunks)},
372d0e79aa3SJason Evans 	{NAME("hchunk"),	CHILD(indexed, arenas_hchunk)},
37382872ac0SJason Evans 	{NAME("extend"),	CTL(arenas_extend)}
374a4bd5210SJason Evans };
375a4bd5210SJason Evans 
376e722f8f8SJason Evans static const ctl_named_node_t	prof_node[] = {
377d0e79aa3SJason Evans 	{NAME("thread_active_init"), CTL(prof_thread_active_init)},
378a4bd5210SJason Evans 	{NAME("active"),	CTL(prof_active)},
379a4bd5210SJason Evans 	{NAME("dump"),		CTL(prof_dump)},
380d0e79aa3SJason Evans 	{NAME("gdump"),		CTL(prof_gdump)},
381d0e79aa3SJason Evans 	{NAME("reset"),		CTL(prof_reset)},
382d0e79aa3SJason Evans 	{NAME("interval"),	CTL(prof_interval)},
383d0e79aa3SJason Evans 	{NAME("lg_sample"),	CTL(lg_prof_sample)}
384a4bd5210SJason Evans };
385a4bd5210SJason Evans 
386d0e79aa3SJason Evans static const ctl_named_node_t stats_arenas_i_metadata_node[] = {
387d0e79aa3SJason Evans 	{NAME("mapped"),	CTL(stats_arenas_i_metadata_mapped)},
388d0e79aa3SJason Evans 	{NAME("allocated"),	CTL(stats_arenas_i_metadata_allocated)}
389a4bd5210SJason Evans };
390a4bd5210SJason Evans 
391e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_small_node[] = {
392a4bd5210SJason Evans 	{NAME("allocated"),	CTL(stats_arenas_i_small_allocated)},
393a4bd5210SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_small_nmalloc)},
394a4bd5210SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_small_ndalloc)},
395a4bd5210SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_small_nrequests)}
396a4bd5210SJason Evans };
397a4bd5210SJason Evans 
398e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_large_node[] = {
399a4bd5210SJason Evans 	{NAME("allocated"),	CTL(stats_arenas_i_large_allocated)},
400a4bd5210SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_large_nmalloc)},
401a4bd5210SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_large_ndalloc)},
402a4bd5210SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_large_nrequests)}
403a4bd5210SJason Evans };
404a4bd5210SJason Evans 
405d0e79aa3SJason Evans static const ctl_named_node_t stats_arenas_i_huge_node[] = {
406d0e79aa3SJason Evans 	{NAME("allocated"),	CTL(stats_arenas_i_huge_allocated)},
407d0e79aa3SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_huge_nmalloc)},
408d0e79aa3SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_huge_ndalloc)},
409d0e79aa3SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_huge_nrequests)}
410d0e79aa3SJason Evans };
411d0e79aa3SJason Evans 
412e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_bins_j_node[] = {
413a4bd5210SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_bins_j_nmalloc)},
414a4bd5210SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_bins_j_ndalloc)},
415a4bd5210SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_bins_j_nrequests)},
416d0e79aa3SJason Evans 	{NAME("curregs"),	CTL(stats_arenas_i_bins_j_curregs)},
417a4bd5210SJason Evans 	{NAME("nfills"),	CTL(stats_arenas_i_bins_j_nfills)},
418a4bd5210SJason Evans 	{NAME("nflushes"),	CTL(stats_arenas_i_bins_j_nflushes)},
419a4bd5210SJason Evans 	{NAME("nruns"),		CTL(stats_arenas_i_bins_j_nruns)},
420a4bd5210SJason Evans 	{NAME("nreruns"),	CTL(stats_arenas_i_bins_j_nreruns)},
421a4bd5210SJason Evans 	{NAME("curruns"),	CTL(stats_arenas_i_bins_j_curruns)}
422a4bd5210SJason Evans };
423e722f8f8SJason Evans static const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {
424e722f8f8SJason Evans 	{NAME(""),		CHILD(named, stats_arenas_i_bins_j)}
425a4bd5210SJason Evans };
426a4bd5210SJason Evans 
427e722f8f8SJason Evans static const ctl_indexed_node_t stats_arenas_i_bins_node[] = {
428a4bd5210SJason Evans 	{INDEX(stats_arenas_i_bins_j)}
429a4bd5210SJason Evans };
430a4bd5210SJason Evans 
431e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {
432a4bd5210SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_lruns_j_nmalloc)},
433a4bd5210SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_lruns_j_ndalloc)},
434a4bd5210SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_lruns_j_nrequests)},
435a4bd5210SJason Evans 	{NAME("curruns"),	CTL(stats_arenas_i_lruns_j_curruns)}
436a4bd5210SJason Evans };
437e722f8f8SJason Evans static const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {
438e722f8f8SJason Evans 	{NAME(""),		CHILD(named, stats_arenas_i_lruns_j)}
439a4bd5210SJason Evans };
440a4bd5210SJason Evans 
441e722f8f8SJason Evans static const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {
442a4bd5210SJason Evans 	{INDEX(stats_arenas_i_lruns_j)}
443a4bd5210SJason Evans };
444a4bd5210SJason Evans 
445d0e79aa3SJason Evans static const ctl_named_node_t stats_arenas_i_hchunks_j_node[] = {
446d0e79aa3SJason Evans 	{NAME("nmalloc"),	CTL(stats_arenas_i_hchunks_j_nmalloc)},
447d0e79aa3SJason Evans 	{NAME("ndalloc"),	CTL(stats_arenas_i_hchunks_j_ndalloc)},
448d0e79aa3SJason Evans 	{NAME("nrequests"),	CTL(stats_arenas_i_hchunks_j_nrequests)},
449d0e79aa3SJason Evans 	{NAME("curhchunks"),	CTL(stats_arenas_i_hchunks_j_curhchunks)}
450d0e79aa3SJason Evans };
451d0e79aa3SJason Evans static const ctl_named_node_t super_stats_arenas_i_hchunks_j_node[] = {
452d0e79aa3SJason Evans 	{NAME(""),		CHILD(named, stats_arenas_i_hchunks_j)}
453d0e79aa3SJason Evans };
454d0e79aa3SJason Evans 
455d0e79aa3SJason Evans static const ctl_indexed_node_t stats_arenas_i_hchunks_node[] = {
456d0e79aa3SJason Evans 	{INDEX(stats_arenas_i_hchunks_j)}
457d0e79aa3SJason Evans };
458d0e79aa3SJason Evans 
459e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_node[] = {
460a4bd5210SJason Evans 	{NAME("nthreads"),	CTL(stats_arenas_i_nthreads)},
46182872ac0SJason Evans 	{NAME("dss"),		CTL(stats_arenas_i_dss)},
462d0e79aa3SJason Evans 	{NAME("lg_dirty_mult"),	CTL(stats_arenas_i_lg_dirty_mult)},
463df0d881dSJason Evans 	{NAME("decay_time"),	CTL(stats_arenas_i_decay_time)},
464a4bd5210SJason Evans 	{NAME("pactive"),	CTL(stats_arenas_i_pactive)},
465a4bd5210SJason Evans 	{NAME("pdirty"),	CTL(stats_arenas_i_pdirty)},
466a4bd5210SJason Evans 	{NAME("mapped"),	CTL(stats_arenas_i_mapped)},
4671f0a49e8SJason Evans 	{NAME("retained"),	CTL(stats_arenas_i_retained)},
468a4bd5210SJason Evans 	{NAME("npurge"),	CTL(stats_arenas_i_npurge)},
469a4bd5210SJason Evans 	{NAME("nmadvise"),	CTL(stats_arenas_i_nmadvise)},
470a4bd5210SJason Evans 	{NAME("purged"),	CTL(stats_arenas_i_purged)},
471d0e79aa3SJason Evans 	{NAME("metadata"),	CHILD(named, stats_arenas_i_metadata)},
472e722f8f8SJason Evans 	{NAME("small"),		CHILD(named, stats_arenas_i_small)},
473e722f8f8SJason Evans 	{NAME("large"),		CHILD(named, stats_arenas_i_large)},
474d0e79aa3SJason Evans 	{NAME("huge"),		CHILD(named, stats_arenas_i_huge)},
475e722f8f8SJason Evans 	{NAME("bins"),		CHILD(indexed, stats_arenas_i_bins)},
476d0e79aa3SJason Evans 	{NAME("lruns"),		CHILD(indexed, stats_arenas_i_lruns)},
477d0e79aa3SJason Evans 	{NAME("hchunks"),	CHILD(indexed, stats_arenas_i_hchunks)}
478a4bd5210SJason Evans };
479e722f8f8SJason Evans static const ctl_named_node_t super_stats_arenas_i_node[] = {
480e722f8f8SJason Evans 	{NAME(""),		CHILD(named, stats_arenas_i)}
481a4bd5210SJason Evans };
482a4bd5210SJason Evans 
483e722f8f8SJason Evans static const ctl_indexed_node_t stats_arenas_node[] = {
484a4bd5210SJason Evans 	{INDEX(stats_arenas_i)}
485a4bd5210SJason Evans };
486a4bd5210SJason Evans 
487e722f8f8SJason Evans static const ctl_named_node_t stats_node[] = {
488a4bd5210SJason Evans 	{NAME("cactive"),	CTL(stats_cactive)},
489a4bd5210SJason Evans 	{NAME("allocated"),	CTL(stats_allocated)},
490a4bd5210SJason Evans 	{NAME("active"),	CTL(stats_active)},
491d0e79aa3SJason Evans 	{NAME("metadata"),	CTL(stats_metadata)},
492d0e79aa3SJason Evans 	{NAME("resident"),	CTL(stats_resident)},
493a4bd5210SJason Evans 	{NAME("mapped"),	CTL(stats_mapped)},
4941f0a49e8SJason Evans 	{NAME("retained"),	CTL(stats_retained)},
495e722f8f8SJason Evans 	{NAME("arenas"),	CHILD(indexed, stats_arenas)}
496a4bd5210SJason Evans };
497a4bd5210SJason Evans 
498e722f8f8SJason Evans static const ctl_named_node_t	root_node[] = {
499a4bd5210SJason Evans 	{NAME("version"),	CTL(version)},
500a4bd5210SJason Evans 	{NAME("epoch"),		CTL(epoch)},
501e722f8f8SJason Evans 	{NAME("thread"),	CHILD(named, thread)},
502e722f8f8SJason Evans 	{NAME("config"),	CHILD(named, config)},
503e722f8f8SJason Evans 	{NAME("opt"),		CHILD(named, opt)},
504d0e79aa3SJason Evans 	{NAME("tcache"),	CHILD(named, tcache)},
50582872ac0SJason Evans 	{NAME("arena"),		CHILD(indexed, arena)},
506e722f8f8SJason Evans 	{NAME("arenas"),	CHILD(named, arenas)},
507e722f8f8SJason Evans 	{NAME("prof"),		CHILD(named, prof)},
508e722f8f8SJason Evans 	{NAME("stats"),		CHILD(named, stats)}
509a4bd5210SJason Evans };
510e722f8f8SJason Evans static const ctl_named_node_t super_root_node[] = {
511e722f8f8SJason Evans 	{NAME(""),		CHILD(named, root)}
512a4bd5210SJason Evans };
513a4bd5210SJason Evans 
514a4bd5210SJason Evans #undef NAME
515a4bd5210SJason Evans #undef CHILD
516a4bd5210SJason Evans #undef CTL
517a4bd5210SJason Evans #undef INDEX
518a4bd5210SJason Evans 
519a4bd5210SJason Evans /******************************************************************************/
520a4bd5210SJason Evans 
521a4bd5210SJason Evans static bool
522a4bd5210SJason Evans ctl_arena_init(ctl_arena_stats_t *astats)
523a4bd5210SJason Evans {
524a4bd5210SJason Evans 
525a4bd5210SJason Evans 	if (astats->lstats == NULL) {
526d0e79aa3SJason Evans 		astats->lstats = (malloc_large_stats_t *)a0malloc(nlclasses *
527a4bd5210SJason Evans 		    sizeof(malloc_large_stats_t));
528a4bd5210SJason Evans 		if (astats->lstats == NULL)
529a4bd5210SJason Evans 			return (true);
530a4bd5210SJason Evans 	}
531a4bd5210SJason Evans 
532d0e79aa3SJason Evans 	if (astats->hstats == NULL) {
533d0e79aa3SJason Evans 		astats->hstats = (malloc_huge_stats_t *)a0malloc(nhclasses *
534d0e79aa3SJason Evans 		    sizeof(malloc_huge_stats_t));
535d0e79aa3SJason Evans 		if (astats->hstats == NULL)
536d0e79aa3SJason Evans 			return (true);
537d0e79aa3SJason Evans 	}
538d0e79aa3SJason Evans 
539a4bd5210SJason Evans 	return (false);
540a4bd5210SJason Evans }
541a4bd5210SJason Evans 
542a4bd5210SJason Evans static void
543a4bd5210SJason Evans ctl_arena_clear(ctl_arena_stats_t *astats)
544a4bd5210SJason Evans {
545a4bd5210SJason Evans 
546df0d881dSJason Evans 	astats->nthreads = 0;
54782872ac0SJason Evans 	astats->dss = dss_prec_names[dss_prec_limit];
548d0e79aa3SJason Evans 	astats->lg_dirty_mult = -1;
549df0d881dSJason Evans 	astats->decay_time = -1;
550a4bd5210SJason Evans 	astats->pactive = 0;
551a4bd5210SJason Evans 	astats->pdirty = 0;
552a4bd5210SJason Evans 	if (config_stats) {
553a4bd5210SJason Evans 		memset(&astats->astats, 0, sizeof(arena_stats_t));
554a4bd5210SJason Evans 		astats->allocated_small = 0;
555a4bd5210SJason Evans 		astats->nmalloc_small = 0;
556a4bd5210SJason Evans 		astats->ndalloc_small = 0;
557a4bd5210SJason Evans 		astats->nrequests_small = 0;
558a4bd5210SJason Evans 		memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));
559a4bd5210SJason Evans 		memset(astats->lstats, 0, nlclasses *
560a4bd5210SJason Evans 		    sizeof(malloc_large_stats_t));
561d0e79aa3SJason Evans 		memset(astats->hstats, 0, nhclasses *
562d0e79aa3SJason Evans 		    sizeof(malloc_huge_stats_t));
563a4bd5210SJason Evans 	}
564a4bd5210SJason Evans }
565a4bd5210SJason Evans 
566a4bd5210SJason Evans static void
5671f0a49e8SJason Evans ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_stats_t *cstats, arena_t *arena)
568a4bd5210SJason Evans {
569a4bd5210SJason Evans 	unsigned i;
570a4bd5210SJason Evans 
571df0d881dSJason Evans 	if (config_stats) {
5721f0a49e8SJason Evans 		arena_stats_merge(tsdn, arena, &cstats->nthreads, &cstats->dss,
573df0d881dSJason Evans 		    &cstats->lg_dirty_mult, &cstats->decay_time,
574df0d881dSJason Evans 		    &cstats->pactive, &cstats->pdirty, &cstats->astats,
575df0d881dSJason Evans 		    cstats->bstats, cstats->lstats, cstats->hstats);
576a4bd5210SJason Evans 
577a4bd5210SJason Evans 		for (i = 0; i < NBINS; i++) {
578d0e79aa3SJason Evans 			cstats->allocated_small += cstats->bstats[i].curregs *
579d0e79aa3SJason Evans 			    index2size(i);
580a4bd5210SJason Evans 			cstats->nmalloc_small += cstats->bstats[i].nmalloc;
581a4bd5210SJason Evans 			cstats->ndalloc_small += cstats->bstats[i].ndalloc;
582a4bd5210SJason Evans 			cstats->nrequests_small += cstats->bstats[i].nrequests;
583a4bd5210SJason Evans 		}
584df0d881dSJason Evans 	} else {
5851f0a49e8SJason Evans 		arena_basic_stats_merge(tsdn, arena, &cstats->nthreads,
5861f0a49e8SJason Evans 		    &cstats->dss, &cstats->lg_dirty_mult, &cstats->decay_time,
587df0d881dSJason Evans 		    &cstats->pactive, &cstats->pdirty);
588df0d881dSJason Evans 	}
589a4bd5210SJason Evans }
590a4bd5210SJason Evans 
591a4bd5210SJason Evans static void
592a4bd5210SJason Evans ctl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)
593a4bd5210SJason Evans {
594a4bd5210SJason Evans 	unsigned i;
595a4bd5210SJason Evans 
596df0d881dSJason Evans 	sstats->nthreads += astats->nthreads;
597a4bd5210SJason Evans 	sstats->pactive += astats->pactive;
598a4bd5210SJason Evans 	sstats->pdirty += astats->pdirty;
599a4bd5210SJason Evans 
600df0d881dSJason Evans 	if (config_stats) {
601a4bd5210SJason Evans 		sstats->astats.mapped += astats->astats.mapped;
6021f0a49e8SJason Evans 		sstats->astats.retained += astats->astats.retained;
603a4bd5210SJason Evans 		sstats->astats.npurge += astats->astats.npurge;
604a4bd5210SJason Evans 		sstats->astats.nmadvise += astats->astats.nmadvise;
605a4bd5210SJason Evans 		sstats->astats.purged += astats->astats.purged;
606a4bd5210SJason Evans 
607df0d881dSJason Evans 		sstats->astats.metadata_mapped +=
608df0d881dSJason Evans 		    astats->astats.metadata_mapped;
609df0d881dSJason Evans 		sstats->astats.metadata_allocated +=
610df0d881dSJason Evans 		    astats->astats.metadata_allocated;
611d0e79aa3SJason Evans 
612a4bd5210SJason Evans 		sstats->allocated_small += astats->allocated_small;
613a4bd5210SJason Evans 		sstats->nmalloc_small += astats->nmalloc_small;
614a4bd5210SJason Evans 		sstats->ndalloc_small += astats->ndalloc_small;
615a4bd5210SJason Evans 		sstats->nrequests_small += astats->nrequests_small;
616a4bd5210SJason Evans 
617df0d881dSJason Evans 		sstats->astats.allocated_large +=
618df0d881dSJason Evans 		    astats->astats.allocated_large;
619a4bd5210SJason Evans 		sstats->astats.nmalloc_large += astats->astats.nmalloc_large;
620a4bd5210SJason Evans 		sstats->astats.ndalloc_large += astats->astats.ndalloc_large;
621df0d881dSJason Evans 		sstats->astats.nrequests_large +=
622df0d881dSJason Evans 		    astats->astats.nrequests_large;
623a4bd5210SJason Evans 
624d0e79aa3SJason Evans 		sstats->astats.allocated_huge += astats->astats.allocated_huge;
625d0e79aa3SJason Evans 		sstats->astats.nmalloc_huge += astats->astats.nmalloc_huge;
626d0e79aa3SJason Evans 		sstats->astats.ndalloc_huge += astats->astats.ndalloc_huge;
627a4bd5210SJason Evans 
628a4bd5210SJason Evans 		for (i = 0; i < NBINS; i++) {
629a4bd5210SJason Evans 			sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
630a4bd5210SJason Evans 			sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
631df0d881dSJason Evans 			sstats->bstats[i].nrequests +=
632df0d881dSJason Evans 			    astats->bstats[i].nrequests;
633d0e79aa3SJason Evans 			sstats->bstats[i].curregs += astats->bstats[i].curregs;
634a4bd5210SJason Evans 			if (config_tcache) {
635df0d881dSJason Evans 				sstats->bstats[i].nfills +=
636df0d881dSJason Evans 				    astats->bstats[i].nfills;
637a4bd5210SJason Evans 				sstats->bstats[i].nflushes +=
638a4bd5210SJason Evans 				    astats->bstats[i].nflushes;
639a4bd5210SJason Evans 			}
640a4bd5210SJason Evans 			sstats->bstats[i].nruns += astats->bstats[i].nruns;
641a4bd5210SJason Evans 			sstats->bstats[i].reruns += astats->bstats[i].reruns;
642a4bd5210SJason Evans 			sstats->bstats[i].curruns += astats->bstats[i].curruns;
643a4bd5210SJason Evans 		}
644d0e79aa3SJason Evans 
645d0e79aa3SJason Evans 		for (i = 0; i < nlclasses; i++) {
646d0e79aa3SJason Evans 			sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;
647d0e79aa3SJason Evans 			sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;
648df0d881dSJason Evans 			sstats->lstats[i].nrequests +=
649df0d881dSJason Evans 			    astats->lstats[i].nrequests;
650d0e79aa3SJason Evans 			sstats->lstats[i].curruns += astats->lstats[i].curruns;
651d0e79aa3SJason Evans 		}
652d0e79aa3SJason Evans 
653d0e79aa3SJason Evans 		for (i = 0; i < nhclasses; i++) {
654d0e79aa3SJason Evans 			sstats->hstats[i].nmalloc += astats->hstats[i].nmalloc;
655d0e79aa3SJason Evans 			sstats->hstats[i].ndalloc += astats->hstats[i].ndalloc;
656df0d881dSJason Evans 			sstats->hstats[i].curhchunks +=
657df0d881dSJason Evans 			    astats->hstats[i].curhchunks;
658df0d881dSJason Evans 		}
659d0e79aa3SJason Evans 	}
660a4bd5210SJason Evans }
661a4bd5210SJason Evans 
662a4bd5210SJason Evans static void
6631f0a49e8SJason Evans ctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, unsigned i)
664a4bd5210SJason Evans {
665a4bd5210SJason Evans 	ctl_arena_stats_t *astats = &ctl_stats.arenas[i];
66682872ac0SJason Evans 	ctl_arena_stats_t *sstats = &ctl_stats.arenas[ctl_stats.narenas];
667a4bd5210SJason Evans 
668a4bd5210SJason Evans 	ctl_arena_clear(astats);
6691f0a49e8SJason Evans 	ctl_arena_stats_amerge(tsdn, astats, arena);
670a4bd5210SJason Evans 	/* Merge into sum stats as well. */
671a4bd5210SJason Evans 	ctl_arena_stats_smerge(sstats, astats);
672a4bd5210SJason Evans }
673a4bd5210SJason Evans 
67482872ac0SJason Evans static bool
6751f0a49e8SJason Evans ctl_grow(tsdn_t *tsdn)
67682872ac0SJason Evans {
67782872ac0SJason Evans 	ctl_arena_stats_t *astats;
67882872ac0SJason Evans 
679d0e79aa3SJason Evans 	/* Initialize new arena. */
6801f0a49e8SJason Evans 	if (arena_init(tsdn, ctl_stats.narenas) == NULL)
681d0e79aa3SJason Evans 		return (true);
682d0e79aa3SJason Evans 
683d0e79aa3SJason Evans 	/* Allocate extended arena stats. */
684d0e79aa3SJason Evans 	astats = (ctl_arena_stats_t *)a0malloc((ctl_stats.narenas + 2) *
6852b06b201SJason Evans 	    sizeof(ctl_arena_stats_t));
68682872ac0SJason Evans 	if (astats == NULL)
68782872ac0SJason Evans 		return (true);
68882872ac0SJason Evans 
6892b06b201SJason Evans 	/* Initialize the new astats element. */
6902b06b201SJason Evans 	memcpy(astats, ctl_stats.arenas, (ctl_stats.narenas + 1) *
6912b06b201SJason Evans 	    sizeof(ctl_arena_stats_t));
6922b06b201SJason Evans 	memset(&astats[ctl_stats.narenas + 1], 0, sizeof(ctl_arena_stats_t));
6932b06b201SJason Evans 	if (ctl_arena_init(&astats[ctl_stats.narenas + 1])) {
694d0e79aa3SJason Evans 		a0dalloc(astats);
69582872ac0SJason Evans 		return (true);
69682872ac0SJason Evans 	}
69782872ac0SJason Evans 	/* Swap merged stats to their new location. */
69882872ac0SJason Evans 	{
69982872ac0SJason Evans 		ctl_arena_stats_t tstats;
70082872ac0SJason Evans 		memcpy(&tstats, &astats[ctl_stats.narenas],
70182872ac0SJason Evans 		    sizeof(ctl_arena_stats_t));
70282872ac0SJason Evans 		memcpy(&astats[ctl_stats.narenas],
70382872ac0SJason Evans 		    &astats[ctl_stats.narenas + 1], sizeof(ctl_arena_stats_t));
70482872ac0SJason Evans 		memcpy(&astats[ctl_stats.narenas + 1], &tstats,
70582872ac0SJason Evans 		    sizeof(ctl_arena_stats_t));
70682872ac0SJason Evans 	}
707d0e79aa3SJason Evans 	a0dalloc(ctl_stats.arenas);
7082b06b201SJason Evans 	ctl_stats.arenas = astats;
7092b06b201SJason Evans 	ctl_stats.narenas++;
71082872ac0SJason Evans 
71182872ac0SJason Evans 	return (false);
71282872ac0SJason Evans }
71382872ac0SJason Evans 
714a4bd5210SJason Evans static void
7151f0a49e8SJason Evans ctl_refresh(tsdn_t *tsdn)
716a4bd5210SJason Evans {
717a4bd5210SJason Evans 	unsigned i;
71882872ac0SJason Evans 	VARIABLE_ARRAY(arena_t *, tarenas, ctl_stats.narenas);
719a4bd5210SJason Evans 
720a4bd5210SJason Evans 	/*
721a4bd5210SJason Evans 	 * Clear sum stats, since they will be merged into by
722a4bd5210SJason Evans 	 * ctl_arena_refresh().
723a4bd5210SJason Evans 	 */
72482872ac0SJason Evans 	ctl_arena_clear(&ctl_stats.arenas[ctl_stats.narenas]);
725a4bd5210SJason Evans 
726df0d881dSJason Evans 	for (i = 0; i < ctl_stats.narenas; i++)
7271f0a49e8SJason Evans 		tarenas[i] = arena_get(tsdn, i, false);
728d0e79aa3SJason Evans 
72982872ac0SJason Evans 	for (i = 0; i < ctl_stats.narenas; i++) {
730a4bd5210SJason Evans 		bool initialized = (tarenas[i] != NULL);
731a4bd5210SJason Evans 
732a4bd5210SJason Evans 		ctl_stats.arenas[i].initialized = initialized;
733a4bd5210SJason Evans 		if (initialized)
7341f0a49e8SJason Evans 			ctl_arena_refresh(tsdn, tarenas[i], i);
735a4bd5210SJason Evans 	}
736a4bd5210SJason Evans 
737a4bd5210SJason Evans 	if (config_stats) {
738d0e79aa3SJason Evans 		size_t base_allocated, base_resident, base_mapped;
7391f0a49e8SJason Evans 		base_stats_get(tsdn, &base_allocated, &base_resident,
7401f0a49e8SJason Evans 		    &base_mapped);
74182872ac0SJason Evans 		ctl_stats.allocated =
742d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].allocated_small +
743d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_large +
744d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.allocated_huge;
74582872ac0SJason Evans 		ctl_stats.active =
746d0e79aa3SJason Evans 		    (ctl_stats.arenas[ctl_stats.narenas].pactive << LG_PAGE);
747d0e79aa3SJason Evans 		ctl_stats.metadata = base_allocated +
748d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +
749d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats
750d0e79aa3SJason Evans 		    .metadata_allocated;
751d0e79aa3SJason Evans 		ctl_stats.resident = base_resident +
752d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.metadata_mapped +
753d0e79aa3SJason Evans 		    ((ctl_stats.arenas[ctl_stats.narenas].pactive +
754d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].pdirty) << LG_PAGE);
755d0e79aa3SJason Evans 		ctl_stats.mapped = base_mapped +
756d0e79aa3SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.mapped;
7571f0a49e8SJason Evans 		ctl_stats.retained =
7581f0a49e8SJason Evans 		    ctl_stats.arenas[ctl_stats.narenas].astats.retained;
759a4bd5210SJason Evans 	}
760a4bd5210SJason Evans 
761a4bd5210SJason Evans 	ctl_epoch++;
762a4bd5210SJason Evans }
763a4bd5210SJason Evans 
764a4bd5210SJason Evans static bool
7651f0a49e8SJason Evans ctl_init(tsdn_t *tsdn)
766a4bd5210SJason Evans {
767a4bd5210SJason Evans 	bool ret;
768a4bd5210SJason Evans 
7691f0a49e8SJason Evans 	malloc_mutex_lock(tsdn, &ctl_mtx);
770d0e79aa3SJason Evans 	if (!ctl_initialized) {
771a4bd5210SJason Evans 		/*
772a4bd5210SJason Evans 		 * Allocate space for one extra arena stats element, which
773a4bd5210SJason Evans 		 * contains summed stats across all arenas.
774a4bd5210SJason Evans 		 */
775d0e79aa3SJason Evans 		ctl_stats.narenas = narenas_total_get();
776d0e79aa3SJason Evans 		ctl_stats.arenas = (ctl_arena_stats_t *)a0malloc(
77782872ac0SJason Evans 		    (ctl_stats.narenas + 1) * sizeof(ctl_arena_stats_t));
778a4bd5210SJason Evans 		if (ctl_stats.arenas == NULL) {
779a4bd5210SJason Evans 			ret = true;
780a4bd5210SJason Evans 			goto label_return;
781a4bd5210SJason Evans 		}
78282872ac0SJason Evans 		memset(ctl_stats.arenas, 0, (ctl_stats.narenas + 1) *
783a4bd5210SJason Evans 		    sizeof(ctl_arena_stats_t));
784a4bd5210SJason Evans 
785a4bd5210SJason Evans 		/*
786a4bd5210SJason Evans 		 * Initialize all stats structures, regardless of whether they
787a4bd5210SJason Evans 		 * ever get used.  Lazy initialization would allow errors to
788a4bd5210SJason Evans 		 * cause inconsistent state to be viewable by the application.
789a4bd5210SJason Evans 		 */
790a4bd5210SJason Evans 		if (config_stats) {
791a4bd5210SJason Evans 			unsigned i;
79282872ac0SJason Evans 			for (i = 0; i <= ctl_stats.narenas; i++) {
793a4bd5210SJason Evans 				if (ctl_arena_init(&ctl_stats.arenas[i])) {
794d0e79aa3SJason Evans 					unsigned j;
795d0e79aa3SJason Evans 					for (j = 0; j < i; j++) {
796d0e79aa3SJason Evans 						a0dalloc(
797d0e79aa3SJason Evans 						    ctl_stats.arenas[j].lstats);
798d0e79aa3SJason Evans 						a0dalloc(
799d0e79aa3SJason Evans 						    ctl_stats.arenas[j].hstats);
800d0e79aa3SJason Evans 					}
801d0e79aa3SJason Evans 					a0dalloc(ctl_stats.arenas);
802d0e79aa3SJason Evans 					ctl_stats.arenas = NULL;
803a4bd5210SJason Evans 					ret = true;
804a4bd5210SJason Evans 					goto label_return;
805a4bd5210SJason Evans 				}
806a4bd5210SJason Evans 			}
807a4bd5210SJason Evans 		}
80882872ac0SJason Evans 		ctl_stats.arenas[ctl_stats.narenas].initialized = true;
809a4bd5210SJason Evans 
810a4bd5210SJason Evans 		ctl_epoch = 0;
8111f0a49e8SJason Evans 		ctl_refresh(tsdn);
812a4bd5210SJason Evans 		ctl_initialized = true;
813a4bd5210SJason Evans 	}
814a4bd5210SJason Evans 
815a4bd5210SJason Evans 	ret = false;
816a4bd5210SJason Evans label_return:
8171f0a49e8SJason Evans 	malloc_mutex_unlock(tsdn, &ctl_mtx);
818a4bd5210SJason Evans 	return (ret);
819a4bd5210SJason Evans }
820a4bd5210SJason Evans 
821a4bd5210SJason Evans static int
8221f0a49e8SJason Evans ctl_lookup(tsdn_t *tsdn, const char *name, ctl_node_t const **nodesp,
8231f0a49e8SJason Evans     size_t *mibp, size_t *depthp)
824a4bd5210SJason Evans {
825a4bd5210SJason Evans 	int ret;
826a4bd5210SJason Evans 	const char *elm, *tdot, *dot;
827a4bd5210SJason Evans 	size_t elen, i, j;
828e722f8f8SJason Evans 	const ctl_named_node_t *node;
829a4bd5210SJason Evans 
830a4bd5210SJason Evans 	elm = name;
831a4bd5210SJason Evans 	/* Equivalent to strchrnul(). */
832a4bd5210SJason Evans 	dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
833a4bd5210SJason Evans 	elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
834a4bd5210SJason Evans 	if (elen == 0) {
835a4bd5210SJason Evans 		ret = ENOENT;
836a4bd5210SJason Evans 		goto label_return;
837a4bd5210SJason Evans 	}
838a4bd5210SJason Evans 	node = super_root_node;
839a4bd5210SJason Evans 	for (i = 0; i < *depthp; i++) {
840e722f8f8SJason Evans 		assert(node);
841e722f8f8SJason Evans 		assert(node->nchildren > 0);
842e722f8f8SJason Evans 		if (ctl_named_node(node->children) != NULL) {
843e722f8f8SJason Evans 			const ctl_named_node_t *pnode = node;
844a4bd5210SJason Evans 
845a4bd5210SJason Evans 			/* Children are named. */
846e722f8f8SJason Evans 			for (j = 0; j < node->nchildren; j++) {
847e722f8f8SJason Evans 				const ctl_named_node_t *child =
848e722f8f8SJason Evans 				    ctl_named_children(node, j);
849e722f8f8SJason Evans 				if (strlen(child->name) == elen &&
850e722f8f8SJason Evans 				    strncmp(elm, child->name, elen) == 0) {
851a4bd5210SJason Evans 					node = child;
852a4bd5210SJason Evans 					if (nodesp != NULL)
853e722f8f8SJason Evans 						nodesp[i] =
854e722f8f8SJason Evans 						    (const ctl_node_t *)node;
855a4bd5210SJason Evans 					mibp[i] = j;
856a4bd5210SJason Evans 					break;
857a4bd5210SJason Evans 				}
858a4bd5210SJason Evans 			}
859a4bd5210SJason Evans 			if (node == pnode) {
860a4bd5210SJason Evans 				ret = ENOENT;
861a4bd5210SJason Evans 				goto label_return;
862a4bd5210SJason Evans 			}
863a4bd5210SJason Evans 		} else {
864a4bd5210SJason Evans 			uintmax_t index;
865e722f8f8SJason Evans 			const ctl_indexed_node_t *inode;
866a4bd5210SJason Evans 
867a4bd5210SJason Evans 			/* Children are indexed. */
868a4bd5210SJason Evans 			index = malloc_strtoumax(elm, NULL, 10);
869a4bd5210SJason Evans 			if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
870a4bd5210SJason Evans 				ret = ENOENT;
871a4bd5210SJason Evans 				goto label_return;
872a4bd5210SJason Evans 			}
873a4bd5210SJason Evans 
874e722f8f8SJason Evans 			inode = ctl_indexed_node(node->children);
8751f0a49e8SJason Evans 			node = inode->index(tsdn, mibp, *depthp, (size_t)index);
876a4bd5210SJason Evans 			if (node == NULL) {
877a4bd5210SJason Evans 				ret = ENOENT;
878a4bd5210SJason Evans 				goto label_return;
879a4bd5210SJason Evans 			}
880a4bd5210SJason Evans 
881a4bd5210SJason Evans 			if (nodesp != NULL)
882e722f8f8SJason Evans 				nodesp[i] = (const ctl_node_t *)node;
883a4bd5210SJason Evans 			mibp[i] = (size_t)index;
884a4bd5210SJason Evans 		}
885a4bd5210SJason Evans 
886a4bd5210SJason Evans 		if (node->ctl != NULL) {
887a4bd5210SJason Evans 			/* Terminal node. */
888a4bd5210SJason Evans 			if (*dot != '\0') {
889a4bd5210SJason Evans 				/*
890a4bd5210SJason Evans 				 * The name contains more elements than are
891a4bd5210SJason Evans 				 * in this path through the tree.
892a4bd5210SJason Evans 				 */
893a4bd5210SJason Evans 				ret = ENOENT;
894a4bd5210SJason Evans 				goto label_return;
895a4bd5210SJason Evans 			}
896a4bd5210SJason Evans 			/* Complete lookup successful. */
897a4bd5210SJason Evans 			*depthp = i + 1;
898a4bd5210SJason Evans 			break;
899a4bd5210SJason Evans 		}
900a4bd5210SJason Evans 
901a4bd5210SJason Evans 		/* Update elm. */
902a4bd5210SJason Evans 		if (*dot == '\0') {
903a4bd5210SJason Evans 			/* No more elements. */
904a4bd5210SJason Evans 			ret = ENOENT;
905a4bd5210SJason Evans 			goto label_return;
906a4bd5210SJason Evans 		}
907a4bd5210SJason Evans 		elm = &dot[1];
908a4bd5210SJason Evans 		dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
909a4bd5210SJason Evans 		    strchr(elm, '\0');
910a4bd5210SJason Evans 		elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
911a4bd5210SJason Evans 	}
912a4bd5210SJason Evans 
913a4bd5210SJason Evans 	ret = 0;
914a4bd5210SJason Evans label_return:
915a4bd5210SJason Evans 	return (ret);
916a4bd5210SJason Evans }
917a4bd5210SJason Evans 
918a4bd5210SJason Evans int
9191f0a49e8SJason Evans ctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp,
9201f0a49e8SJason Evans     void *newp, size_t newlen)
921a4bd5210SJason Evans {
922a4bd5210SJason Evans 	int ret;
923a4bd5210SJason Evans 	size_t depth;
924a4bd5210SJason Evans 	ctl_node_t const *nodes[CTL_MAX_DEPTH];
925a4bd5210SJason Evans 	size_t mib[CTL_MAX_DEPTH];
926e722f8f8SJason Evans 	const ctl_named_node_t *node;
927a4bd5210SJason Evans 
9281f0a49e8SJason Evans 	if (!ctl_initialized && ctl_init(tsd_tsdn(tsd))) {
929a4bd5210SJason Evans 		ret = EAGAIN;
930a4bd5210SJason Evans 		goto label_return;
931a4bd5210SJason Evans 	}
932a4bd5210SJason Evans 
933a4bd5210SJason Evans 	depth = CTL_MAX_DEPTH;
9341f0a49e8SJason Evans 	ret = ctl_lookup(tsd_tsdn(tsd), name, nodes, mib, &depth);
935a4bd5210SJason Evans 	if (ret != 0)
936a4bd5210SJason Evans 		goto label_return;
937a4bd5210SJason Evans 
938e722f8f8SJason Evans 	node = ctl_named_node(nodes[depth-1]);
939e722f8f8SJason Evans 	if (node != NULL && node->ctl)
9401f0a49e8SJason Evans 		ret = node->ctl(tsd, mib, depth, oldp, oldlenp, newp, newlen);
941e722f8f8SJason Evans 	else {
942a4bd5210SJason Evans 		/* The name refers to a partial path through the ctl tree. */
943a4bd5210SJason Evans 		ret = ENOENT;
944a4bd5210SJason Evans 	}
945a4bd5210SJason Evans 
946a4bd5210SJason Evans label_return:
947a4bd5210SJason Evans 	return(ret);
948a4bd5210SJason Evans }
949a4bd5210SJason Evans 
950a4bd5210SJason Evans int
9511f0a49e8SJason Evans ctl_nametomib(tsdn_t *tsdn, const char *name, size_t *mibp, size_t *miblenp)
952a4bd5210SJason Evans {
953a4bd5210SJason Evans 	int ret;
954a4bd5210SJason Evans 
9551f0a49e8SJason Evans 	if (!ctl_initialized && ctl_init(tsdn)) {
956a4bd5210SJason Evans 		ret = EAGAIN;
957a4bd5210SJason Evans 		goto label_return;
958a4bd5210SJason Evans 	}
959a4bd5210SJason Evans 
9601f0a49e8SJason Evans 	ret = ctl_lookup(tsdn, name, NULL, mibp, miblenp);
961a4bd5210SJason Evans label_return:
962a4bd5210SJason Evans 	return(ret);
963a4bd5210SJason Evans }
964a4bd5210SJason Evans 
965a4bd5210SJason Evans int
9661f0a49e8SJason Evans ctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
9671f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
968a4bd5210SJason Evans {
969a4bd5210SJason Evans 	int ret;
970e722f8f8SJason Evans 	const ctl_named_node_t *node;
971a4bd5210SJason Evans 	size_t i;
972a4bd5210SJason Evans 
9731f0a49e8SJason Evans 	if (!ctl_initialized && ctl_init(tsd_tsdn(tsd))) {
974a4bd5210SJason Evans 		ret = EAGAIN;
975a4bd5210SJason Evans 		goto label_return;
976a4bd5210SJason Evans 	}
977a4bd5210SJason Evans 
978a4bd5210SJason Evans 	/* Iterate down the tree. */
979a4bd5210SJason Evans 	node = super_root_node;
980a4bd5210SJason Evans 	for (i = 0; i < miblen; i++) {
981e722f8f8SJason Evans 		assert(node);
982e722f8f8SJason Evans 		assert(node->nchildren > 0);
983e722f8f8SJason Evans 		if (ctl_named_node(node->children) != NULL) {
984a4bd5210SJason Evans 			/* Children are named. */
985df0d881dSJason Evans 			if (node->nchildren <= (unsigned)mib[i]) {
986a4bd5210SJason Evans 				ret = ENOENT;
987a4bd5210SJason Evans 				goto label_return;
988a4bd5210SJason Evans 			}
989e722f8f8SJason Evans 			node = ctl_named_children(node, mib[i]);
990a4bd5210SJason Evans 		} else {
991e722f8f8SJason Evans 			const ctl_indexed_node_t *inode;
992a4bd5210SJason Evans 
993a4bd5210SJason Evans 			/* Indexed element. */
994e722f8f8SJason Evans 			inode = ctl_indexed_node(node->children);
9951f0a49e8SJason Evans 			node = inode->index(tsd_tsdn(tsd), mib, miblen, mib[i]);
996a4bd5210SJason Evans 			if (node == NULL) {
997a4bd5210SJason Evans 				ret = ENOENT;
998a4bd5210SJason Evans 				goto label_return;
999a4bd5210SJason Evans 			}
1000a4bd5210SJason Evans 		}
1001a4bd5210SJason Evans 	}
1002a4bd5210SJason Evans 
1003a4bd5210SJason Evans 	/* Call the ctl function. */
1004e722f8f8SJason Evans 	if (node && node->ctl)
10051f0a49e8SJason Evans 		ret = node->ctl(tsd, mib, miblen, oldp, oldlenp, newp, newlen);
1006e722f8f8SJason Evans 	else {
1007a4bd5210SJason Evans 		/* Partial MIB. */
1008a4bd5210SJason Evans 		ret = ENOENT;
1009a4bd5210SJason Evans 	}
1010a4bd5210SJason Evans 
1011a4bd5210SJason Evans label_return:
1012a4bd5210SJason Evans 	return(ret);
1013a4bd5210SJason Evans }
1014a4bd5210SJason Evans 
1015a4bd5210SJason Evans bool
1016a4bd5210SJason Evans ctl_boot(void)
1017a4bd5210SJason Evans {
1018a4bd5210SJason Evans 
10191f0a49e8SJason Evans 	if (malloc_mutex_init(&ctl_mtx, "ctl", WITNESS_RANK_CTL))
1020a4bd5210SJason Evans 		return (true);
1021a4bd5210SJason Evans 
1022a4bd5210SJason Evans 	ctl_initialized = false;
1023a4bd5210SJason Evans 
1024a4bd5210SJason Evans 	return (false);
1025a4bd5210SJason Evans }
1026a4bd5210SJason Evans 
102782872ac0SJason Evans void
10281f0a49e8SJason Evans ctl_prefork(tsdn_t *tsdn)
102982872ac0SJason Evans {
103082872ac0SJason Evans 
10311f0a49e8SJason Evans 	malloc_mutex_prefork(tsdn, &ctl_mtx);
103282872ac0SJason Evans }
103382872ac0SJason Evans 
103482872ac0SJason Evans void
10351f0a49e8SJason Evans ctl_postfork_parent(tsdn_t *tsdn)
103682872ac0SJason Evans {
103782872ac0SJason Evans 
10381f0a49e8SJason Evans 	malloc_mutex_postfork_parent(tsdn, &ctl_mtx);
103982872ac0SJason Evans }
104082872ac0SJason Evans 
104182872ac0SJason Evans void
10421f0a49e8SJason Evans ctl_postfork_child(tsdn_t *tsdn)
104382872ac0SJason Evans {
104482872ac0SJason Evans 
10451f0a49e8SJason Evans 	malloc_mutex_postfork_child(tsdn, &ctl_mtx);
104682872ac0SJason Evans }
104782872ac0SJason Evans 
1048a4bd5210SJason Evans /******************************************************************************/
1049a4bd5210SJason Evans /* *_ctl() functions. */
1050a4bd5210SJason Evans 
1051a4bd5210SJason Evans #define	READONLY()	do {						\
1052a4bd5210SJason Evans 	if (newp != NULL || newlen != 0) {				\
1053a4bd5210SJason Evans 		ret = EPERM;						\
1054a4bd5210SJason Evans 		goto label_return;					\
1055a4bd5210SJason Evans 	}								\
1056a4bd5210SJason Evans } while (0)
1057a4bd5210SJason Evans 
1058a4bd5210SJason Evans #define	WRITEONLY()	do {						\
1059a4bd5210SJason Evans 	if (oldp != NULL || oldlenp != NULL) {				\
1060a4bd5210SJason Evans 		ret = EPERM;						\
1061a4bd5210SJason Evans 		goto label_return;					\
1062a4bd5210SJason Evans 	}								\
1063a4bd5210SJason Evans } while (0)
1064a4bd5210SJason Evans 
1065d0e79aa3SJason Evans #define	READ_XOR_WRITE()	do {					\
1066d0e79aa3SJason Evans 	if ((oldp != NULL && oldlenp != NULL) && (newp != NULL ||	\
1067d0e79aa3SJason Evans 	    newlen != 0)) {						\
1068d0e79aa3SJason Evans 		ret = EPERM;						\
1069d0e79aa3SJason Evans 		goto label_return;					\
1070d0e79aa3SJason Evans 	}								\
1071d0e79aa3SJason Evans } while (0)
1072d0e79aa3SJason Evans 
1073a4bd5210SJason Evans #define	READ(v, t)	do {						\
1074a4bd5210SJason Evans 	if (oldp != NULL && oldlenp != NULL) {				\
1075a4bd5210SJason Evans 		if (*oldlenp != sizeof(t)) {				\
1076a4bd5210SJason Evans 			size_t	copylen = (sizeof(t) <= *oldlenp)	\
1077a4bd5210SJason Evans 			    ? sizeof(t) : *oldlenp;			\
107888ad2f8dSJason Evans 			memcpy(oldp, (void *)&(v), copylen);		\
1079a4bd5210SJason Evans 			ret = EINVAL;					\
1080a4bd5210SJason Evans 			goto label_return;				\
1081d0e79aa3SJason Evans 		}							\
108288ad2f8dSJason Evans 		*(t *)oldp = (v);					\
1083a4bd5210SJason Evans 	}								\
1084a4bd5210SJason Evans } while (0)
1085a4bd5210SJason Evans 
1086a4bd5210SJason Evans #define	WRITE(v, t)	do {						\
1087a4bd5210SJason Evans 	if (newp != NULL) {						\
1088a4bd5210SJason Evans 		if (newlen != sizeof(t)) {				\
1089a4bd5210SJason Evans 			ret = EINVAL;					\
1090a4bd5210SJason Evans 			goto label_return;				\
1091a4bd5210SJason Evans 		}							\
109288ad2f8dSJason Evans 		(v) = *(t *)newp;					\
1093a4bd5210SJason Evans 	}								\
1094a4bd5210SJason Evans } while (0)
1095a4bd5210SJason Evans 
1096a4bd5210SJason Evans /*
1097a4bd5210SJason Evans  * There's a lot of code duplication in the following macros due to limitations
1098a4bd5210SJason Evans  * in how nested cpp macros are expanded.
1099a4bd5210SJason Evans  */
1100a4bd5210SJason Evans #define	CTL_RO_CLGEN(c, l, n, v, t)					\
1101a4bd5210SJason Evans static int								\
11021f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11031f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1104a4bd5210SJason Evans {									\
1105a4bd5210SJason Evans 	int ret;							\
1106a4bd5210SJason Evans 	t oldval;							\
1107a4bd5210SJason Evans 									\
1108d0e79aa3SJason Evans 	if (!(c))							\
1109a4bd5210SJason Evans 		return (ENOENT);					\
1110a4bd5210SJason Evans 	if (l)								\
11111f0a49e8SJason Evans 		malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);		\
1112a4bd5210SJason Evans 	READONLY();							\
111388ad2f8dSJason Evans 	oldval = (v);							\
1114a4bd5210SJason Evans 	READ(oldval, t);						\
1115a4bd5210SJason Evans 									\
1116a4bd5210SJason Evans 	ret = 0;							\
1117a4bd5210SJason Evans label_return:								\
1118a4bd5210SJason Evans 	if (l)								\
11191f0a49e8SJason Evans 		malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);		\
1120a4bd5210SJason Evans 	return (ret);							\
1121a4bd5210SJason Evans }
1122a4bd5210SJason Evans 
1123a4bd5210SJason Evans #define	CTL_RO_CGEN(c, n, v, t)						\
1124a4bd5210SJason Evans static int								\
11251f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11261f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1127a4bd5210SJason Evans {									\
1128a4bd5210SJason Evans 	int ret;							\
1129a4bd5210SJason Evans 	t oldval;							\
1130a4bd5210SJason Evans 									\
1131d0e79aa3SJason Evans 	if (!(c))							\
1132a4bd5210SJason Evans 		return (ENOENT);					\
11331f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);			\
1134a4bd5210SJason Evans 	READONLY();							\
113588ad2f8dSJason Evans 	oldval = (v);							\
1136a4bd5210SJason Evans 	READ(oldval, t);						\
1137a4bd5210SJason Evans 									\
1138a4bd5210SJason Evans 	ret = 0;							\
1139a4bd5210SJason Evans label_return:								\
11401f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);			\
1141a4bd5210SJason Evans 	return (ret);							\
1142a4bd5210SJason Evans }
1143a4bd5210SJason Evans 
1144a4bd5210SJason Evans #define	CTL_RO_GEN(n, v, t)						\
1145a4bd5210SJason Evans static int								\
11461f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11471f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1148a4bd5210SJason Evans {									\
1149a4bd5210SJason Evans 	int ret;							\
1150a4bd5210SJason Evans 	t oldval;							\
1151a4bd5210SJason Evans 									\
11521f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);			\
1153a4bd5210SJason Evans 	READONLY();							\
115488ad2f8dSJason Evans 	oldval = (v);							\
1155a4bd5210SJason Evans 	READ(oldval, t);						\
1156a4bd5210SJason Evans 									\
1157a4bd5210SJason Evans 	ret = 0;							\
1158a4bd5210SJason Evans label_return:								\
11591f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);			\
1160a4bd5210SJason Evans 	return (ret);							\
1161a4bd5210SJason Evans }
1162a4bd5210SJason Evans 
1163a4bd5210SJason Evans /*
1164a4bd5210SJason Evans  * ctl_mtx is not acquired, under the assumption that no pertinent data will
1165a4bd5210SJason Evans  * mutate during the call.
1166a4bd5210SJason Evans  */
1167a4bd5210SJason Evans #define	CTL_RO_NL_CGEN(c, n, v, t)					\
1168a4bd5210SJason Evans static int								\
11691f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11701f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1171a4bd5210SJason Evans {									\
1172a4bd5210SJason Evans 	int ret;							\
1173a4bd5210SJason Evans 	t oldval;							\
1174a4bd5210SJason Evans 									\
1175d0e79aa3SJason Evans 	if (!(c))							\
1176a4bd5210SJason Evans 		return (ENOENT);					\
1177a4bd5210SJason Evans 	READONLY();							\
117888ad2f8dSJason Evans 	oldval = (v);							\
1179a4bd5210SJason Evans 	READ(oldval, t);						\
1180a4bd5210SJason Evans 									\
1181a4bd5210SJason Evans 	ret = 0;							\
1182a4bd5210SJason Evans label_return:								\
1183a4bd5210SJason Evans 	return (ret);							\
1184a4bd5210SJason Evans }
1185a4bd5210SJason Evans 
1186a4bd5210SJason Evans #define	CTL_RO_NL_GEN(n, v, t)						\
1187a4bd5210SJason Evans static int								\
11881f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
11891f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1190a4bd5210SJason Evans {									\
1191a4bd5210SJason Evans 	int ret;							\
1192a4bd5210SJason Evans 	t oldval;							\
1193a4bd5210SJason Evans 									\
1194a4bd5210SJason Evans 	READONLY();							\
119588ad2f8dSJason Evans 	oldval = (v);							\
1196a4bd5210SJason Evans 	READ(oldval, t);						\
1197a4bd5210SJason Evans 									\
1198a4bd5210SJason Evans 	ret = 0;							\
1199a4bd5210SJason Evans label_return:								\
1200a4bd5210SJason Evans 	return (ret);							\
1201a4bd5210SJason Evans }
1202a4bd5210SJason Evans 
1203d0e79aa3SJason Evans #define	CTL_TSD_RO_NL_CGEN(c, n, m, t)					\
1204d0e79aa3SJason Evans static int								\
12051f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
12061f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1207d0e79aa3SJason Evans {									\
1208d0e79aa3SJason Evans 	int ret;							\
1209d0e79aa3SJason Evans 	t oldval;							\
1210d0e79aa3SJason Evans 									\
1211d0e79aa3SJason Evans 	if (!(c))							\
1212d0e79aa3SJason Evans 		return (ENOENT);					\
1213d0e79aa3SJason Evans 	READONLY();							\
1214d0e79aa3SJason Evans 	oldval = (m(tsd));						\
1215d0e79aa3SJason Evans 	READ(oldval, t);						\
1216d0e79aa3SJason Evans 									\
1217d0e79aa3SJason Evans 	ret = 0;							\
1218d0e79aa3SJason Evans label_return:								\
1219d0e79aa3SJason Evans 	return (ret);							\
1220d0e79aa3SJason Evans }
1221d0e79aa3SJason Evans 
1222df0d881dSJason Evans #define	CTL_RO_CONFIG_GEN(n, t)						\
1223a4bd5210SJason Evans static int								\
12241f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,	\
12251f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)				\
1226a4bd5210SJason Evans {									\
1227a4bd5210SJason Evans 	int ret;							\
1228df0d881dSJason Evans 	t oldval;							\
1229a4bd5210SJason Evans 									\
1230a4bd5210SJason Evans 	READONLY();							\
1231a4bd5210SJason Evans 	oldval = n;							\
1232df0d881dSJason Evans 	READ(oldval, t);						\
1233a4bd5210SJason Evans 									\
1234a4bd5210SJason Evans 	ret = 0;							\
1235a4bd5210SJason Evans label_return:								\
1236a4bd5210SJason Evans 	return (ret);							\
1237a4bd5210SJason Evans }
1238a4bd5210SJason Evans 
1239f921d10fSJason Evans /******************************************************************************/
1240f921d10fSJason Evans 
1241a4bd5210SJason Evans CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
1242a4bd5210SJason Evans 
1243a4bd5210SJason Evans static int
12441f0a49e8SJason Evans epoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
12451f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1246a4bd5210SJason Evans {
1247a4bd5210SJason Evans 	int ret;
12482b06b201SJason Evans 	UNUSED uint64_t newval;
1249a4bd5210SJason Evans 
12501f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1251a4bd5210SJason Evans 	WRITE(newval, uint64_t);
1252e722f8f8SJason Evans 	if (newp != NULL)
12531f0a49e8SJason Evans 		ctl_refresh(tsd_tsdn(tsd));
1254a4bd5210SJason Evans 	READ(ctl_epoch, uint64_t);
1255a4bd5210SJason Evans 
1256a4bd5210SJason Evans 	ret = 0;
1257a4bd5210SJason Evans label_return:
12581f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1259a4bd5210SJason Evans 	return (ret);
1260a4bd5210SJason Evans }
1261a4bd5210SJason Evans 
1262f921d10fSJason Evans /******************************************************************************/
1263a4bd5210SJason Evans 
1264df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_cache_oblivious, bool)
1265df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_debug, bool)
1266df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_fill, bool)
1267df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_lazy_lock, bool)
1268df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_malloc_conf, const char *)
1269df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_munmap, bool)
1270df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof, bool)
1271df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
1272df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
1273df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_stats, bool)
1274df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_tcache, bool)
1275*8244f2aaSJason Evans CTL_RO_CONFIG_GEN(config_thp, bool)
1276df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_tls, bool)
1277df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_utrace, bool)
1278df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_valgrind, bool)
1279df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_xmalloc, bool)
1280a4bd5210SJason Evans 
1281f921d10fSJason Evans /******************************************************************************/
1282a4bd5210SJason Evans 
1283f921d10fSJason Evans CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
1284f921d10fSJason Evans CTL_RO_NL_GEN(opt_dss, opt_dss, const char *)
1285f921d10fSJason Evans CTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
1286df0d881dSJason Evans CTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned)
1287df0d881dSJason Evans CTL_RO_NL_GEN(opt_purge, purge_mode_names[opt_purge], const char *)
1288f921d10fSJason Evans CTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
1289df0d881dSJason Evans CTL_RO_NL_GEN(opt_decay_time, opt_decay_time, ssize_t)
1290f921d10fSJason Evans CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
1291d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)
1292f921d10fSJason Evans CTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
1293f921d10fSJason Evans CTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
1294f921d10fSJason Evans CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
1295f921d10fSJason Evans CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
1296f921d10fSJason Evans CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
1297f921d10fSJason Evans CTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
1298f921d10fSJason Evans CTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
1299*8244f2aaSJason Evans CTL_RO_NL_CGEN(config_thp, opt_thp, opt_thp, bool)
1300f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
1301f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
1302d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool)
1303d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
1304d0e79aa3SJason Evans     opt_prof_thread_active_init, bool)
1305f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
1306f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
1307f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
1308f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
1309f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
1310f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
1311a4bd5210SJason Evans 
1312f921d10fSJason Evans /******************************************************************************/
1313a4bd5210SJason Evans 
1314a4bd5210SJason Evans static int
13151f0a49e8SJason Evans thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
13161f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1317a4bd5210SJason Evans {
1318a4bd5210SJason Evans 	int ret;
1319d0e79aa3SJason Evans 	arena_t *oldarena;
1320a4bd5210SJason Evans 	unsigned newind, oldind;
1321a4bd5210SJason Evans 
1322d0e79aa3SJason Evans 	oldarena = arena_choose(tsd, NULL);
1323d0e79aa3SJason Evans 	if (oldarena == NULL)
1324d0e79aa3SJason Evans 		return (EAGAIN);
1325d0e79aa3SJason Evans 
13261f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1327d0e79aa3SJason Evans 	newind = oldind = oldarena->ind;
1328a4bd5210SJason Evans 	WRITE(newind, unsigned);
1329a4bd5210SJason Evans 	READ(oldind, unsigned);
1330a4bd5210SJason Evans 	if (newind != oldind) {
1331d0e79aa3SJason Evans 		arena_t *newarena;
1332a4bd5210SJason Evans 
133382872ac0SJason Evans 		if (newind >= ctl_stats.narenas) {
1334a4bd5210SJason Evans 			/* New arena index is out of range. */
1335a4bd5210SJason Evans 			ret = EFAULT;
1336a4bd5210SJason Evans 			goto label_return;
1337a4bd5210SJason Evans 		}
1338a4bd5210SJason Evans 
1339a4bd5210SJason Evans 		/* Initialize arena if necessary. */
13401f0a49e8SJason Evans 		newarena = arena_get(tsd_tsdn(tsd), newind, true);
1341d0e79aa3SJason Evans 		if (newarena == NULL) {
1342a4bd5210SJason Evans 			ret = EAGAIN;
1343a4bd5210SJason Evans 			goto label_return;
1344a4bd5210SJason Evans 		}
1345d0e79aa3SJason Evans 		/* Set new arena/tcache associations. */
1346d0e79aa3SJason Evans 		arena_migrate(tsd, oldind, newind);
1347a4bd5210SJason Evans 		if (config_tcache) {
1348d0e79aa3SJason Evans 			tcache_t *tcache = tsd_tcache_get(tsd);
1349d0e79aa3SJason Evans 			if (tcache != NULL) {
13501f0a49e8SJason Evans 				tcache_arena_reassociate(tsd_tsdn(tsd), tcache,
13511f0a49e8SJason Evans 				    oldarena, newarena);
1352a4bd5210SJason Evans 			}
1353a4bd5210SJason Evans 		}
1354a4bd5210SJason Evans 	}
1355a4bd5210SJason Evans 
1356a4bd5210SJason Evans 	ret = 0;
1357a4bd5210SJason Evans label_return:
13581f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1359a4bd5210SJason Evans 	return (ret);
1360a4bd5210SJason Evans }
1361a4bd5210SJason Evans 
1362d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_allocated, tsd_thread_allocated_get,
1363d0e79aa3SJason Evans     uint64_t)
1364d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_allocatedp, tsd_thread_allocatedp_get,
1365d0e79aa3SJason Evans     uint64_t *)
1366d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocated, tsd_thread_deallocated_get,
1367d0e79aa3SJason Evans     uint64_t)
1368d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp,
1369d0e79aa3SJason Evans     tsd_thread_deallocatedp_get, uint64_t *)
1370a4bd5210SJason Evans 
1371f921d10fSJason Evans static int
13721f0a49e8SJason Evans thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
13731f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1374f921d10fSJason Evans {
1375f921d10fSJason Evans 	int ret;
1376f921d10fSJason Evans 	bool oldval;
1377a4bd5210SJason Evans 
1378d0e79aa3SJason Evans 	if (!config_tcache)
1379f921d10fSJason Evans 		return (ENOENT);
1380a4bd5210SJason Evans 
1381f921d10fSJason Evans 	oldval = tcache_enabled_get();
1382f921d10fSJason Evans 	if (newp != NULL) {
1383f921d10fSJason Evans 		if (newlen != sizeof(bool)) {
1384f921d10fSJason Evans 			ret = EINVAL;
1385f921d10fSJason Evans 			goto label_return;
1386f921d10fSJason Evans 		}
1387f921d10fSJason Evans 		tcache_enabled_set(*(bool *)newp);
1388f921d10fSJason Evans 	}
1389f921d10fSJason Evans 	READ(oldval, bool);
1390a4bd5210SJason Evans 
1391f921d10fSJason Evans 	ret = 0;
1392f921d10fSJason Evans label_return:
1393f921d10fSJason Evans 	return (ret);
1394f921d10fSJason Evans }
1395f921d10fSJason Evans 
1396f921d10fSJason Evans static int
13971f0a49e8SJason Evans thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
13981f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1399f921d10fSJason Evans {
1400f921d10fSJason Evans 	int ret;
1401f921d10fSJason Evans 
1402d0e79aa3SJason Evans 	if (!config_tcache)
1403f921d10fSJason Evans 		return (ENOENT);
1404f921d10fSJason Evans 
1405f921d10fSJason Evans 	READONLY();
1406f921d10fSJason Evans 	WRITEONLY();
1407f921d10fSJason Evans 
1408f921d10fSJason Evans 	tcache_flush();
1409f921d10fSJason Evans 
1410f921d10fSJason Evans 	ret = 0;
1411f921d10fSJason Evans label_return:
1412f921d10fSJason Evans 	return (ret);
1413f921d10fSJason Evans }
1414a4bd5210SJason Evans 
1415d0e79aa3SJason Evans static int
14161f0a49e8SJason Evans thread_prof_name_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1417d0e79aa3SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1418d0e79aa3SJason Evans {
1419d0e79aa3SJason Evans 	int ret;
1420d0e79aa3SJason Evans 
1421d0e79aa3SJason Evans 	if (!config_prof)
1422d0e79aa3SJason Evans 		return (ENOENT);
1423d0e79aa3SJason Evans 
1424d0e79aa3SJason Evans 	READ_XOR_WRITE();
1425d0e79aa3SJason Evans 
1426d0e79aa3SJason Evans 	if (newp != NULL) {
1427d0e79aa3SJason Evans 		if (newlen != sizeof(const char *)) {
1428d0e79aa3SJason Evans 			ret = EINVAL;
1429d0e79aa3SJason Evans 			goto label_return;
1430d0e79aa3SJason Evans 		}
1431d0e79aa3SJason Evans 
1432d0e79aa3SJason Evans 		if ((ret = prof_thread_name_set(tsd, *(const char **)newp)) !=
1433d0e79aa3SJason Evans 		    0)
1434d0e79aa3SJason Evans 			goto label_return;
1435d0e79aa3SJason Evans 	} else {
14361f0a49e8SJason Evans 		const char *oldname = prof_thread_name_get(tsd);
1437d0e79aa3SJason Evans 		READ(oldname, const char *);
1438d0e79aa3SJason Evans 	}
1439d0e79aa3SJason Evans 
1440d0e79aa3SJason Evans 	ret = 0;
1441d0e79aa3SJason Evans label_return:
1442d0e79aa3SJason Evans 	return (ret);
1443d0e79aa3SJason Evans }
1444d0e79aa3SJason Evans 
1445d0e79aa3SJason Evans static int
14461f0a49e8SJason Evans thread_prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1447d0e79aa3SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1448d0e79aa3SJason Evans {
1449d0e79aa3SJason Evans 	int ret;
1450d0e79aa3SJason Evans 	bool oldval;
1451d0e79aa3SJason Evans 
1452d0e79aa3SJason Evans 	if (!config_prof)
1453d0e79aa3SJason Evans 		return (ENOENT);
1454d0e79aa3SJason Evans 
14551f0a49e8SJason Evans 	oldval = prof_thread_active_get(tsd);
1456d0e79aa3SJason Evans 	if (newp != NULL) {
1457d0e79aa3SJason Evans 		if (newlen != sizeof(bool)) {
1458d0e79aa3SJason Evans 			ret = EINVAL;
1459d0e79aa3SJason Evans 			goto label_return;
1460d0e79aa3SJason Evans 		}
14611f0a49e8SJason Evans 		if (prof_thread_active_set(tsd, *(bool *)newp)) {
1462d0e79aa3SJason Evans 			ret = EAGAIN;
1463d0e79aa3SJason Evans 			goto label_return;
1464d0e79aa3SJason Evans 		}
1465d0e79aa3SJason Evans 	}
1466d0e79aa3SJason Evans 	READ(oldval, bool);
1467d0e79aa3SJason Evans 
1468d0e79aa3SJason Evans 	ret = 0;
1469d0e79aa3SJason Evans label_return:
1470d0e79aa3SJason Evans 	return (ret);
1471d0e79aa3SJason Evans }
1472d0e79aa3SJason Evans 
1473d0e79aa3SJason Evans /******************************************************************************/
1474d0e79aa3SJason Evans 
1475d0e79aa3SJason Evans static int
14761f0a49e8SJason Evans tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
14771f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1478d0e79aa3SJason Evans {
1479d0e79aa3SJason Evans 	int ret;
1480d0e79aa3SJason Evans 	unsigned tcache_ind;
1481d0e79aa3SJason Evans 
1482d0e79aa3SJason Evans 	if (!config_tcache)
1483d0e79aa3SJason Evans 		return (ENOENT);
1484d0e79aa3SJason Evans 
1485d0e79aa3SJason Evans 	READONLY();
1486bde95144SJason Evans 	if (tcaches_create(tsd, &tcache_ind)) {
1487d0e79aa3SJason Evans 		ret = EFAULT;
1488d0e79aa3SJason Evans 		goto label_return;
1489d0e79aa3SJason Evans 	}
1490d0e79aa3SJason Evans 	READ(tcache_ind, unsigned);
1491d0e79aa3SJason Evans 
1492d0e79aa3SJason Evans 	ret = 0;
1493d0e79aa3SJason Evans label_return:
1494*8244f2aaSJason Evans 	return ret;
1495d0e79aa3SJason Evans }
1496d0e79aa3SJason Evans 
1497d0e79aa3SJason Evans static int
14981f0a49e8SJason Evans tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
14991f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1500d0e79aa3SJason Evans {
1501d0e79aa3SJason Evans 	int ret;
1502d0e79aa3SJason Evans 	unsigned tcache_ind;
1503d0e79aa3SJason Evans 
1504d0e79aa3SJason Evans 	if (!config_tcache)
1505d0e79aa3SJason Evans 		return (ENOENT);
1506d0e79aa3SJason Evans 
1507d0e79aa3SJason Evans 	WRITEONLY();
1508d0e79aa3SJason Evans 	tcache_ind = UINT_MAX;
1509d0e79aa3SJason Evans 	WRITE(tcache_ind, unsigned);
1510d0e79aa3SJason Evans 	if (tcache_ind == UINT_MAX) {
1511d0e79aa3SJason Evans 		ret = EFAULT;
1512d0e79aa3SJason Evans 		goto label_return;
1513d0e79aa3SJason Evans 	}
1514d0e79aa3SJason Evans 	tcaches_flush(tsd, tcache_ind);
1515d0e79aa3SJason Evans 
1516d0e79aa3SJason Evans 	ret = 0;
1517d0e79aa3SJason Evans label_return:
1518d0e79aa3SJason Evans 	return (ret);
1519d0e79aa3SJason Evans }
1520d0e79aa3SJason Evans 
1521d0e79aa3SJason Evans static int
15221f0a49e8SJason Evans tcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1523d0e79aa3SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1524d0e79aa3SJason Evans {
1525d0e79aa3SJason Evans 	int ret;
1526d0e79aa3SJason Evans 	unsigned tcache_ind;
1527d0e79aa3SJason Evans 
1528d0e79aa3SJason Evans 	if (!config_tcache)
1529d0e79aa3SJason Evans 		return (ENOENT);
1530d0e79aa3SJason Evans 
1531d0e79aa3SJason Evans 	WRITEONLY();
1532d0e79aa3SJason Evans 	tcache_ind = UINT_MAX;
1533d0e79aa3SJason Evans 	WRITE(tcache_ind, unsigned);
1534d0e79aa3SJason Evans 	if (tcache_ind == UINT_MAX) {
1535d0e79aa3SJason Evans 		ret = EFAULT;
1536d0e79aa3SJason Evans 		goto label_return;
1537d0e79aa3SJason Evans 	}
1538d0e79aa3SJason Evans 	tcaches_destroy(tsd, tcache_ind);
1539d0e79aa3SJason Evans 
1540d0e79aa3SJason Evans 	ret = 0;
1541d0e79aa3SJason Evans label_return:
1542d0e79aa3SJason Evans 	return (ret);
1543d0e79aa3SJason Evans }
1544d0e79aa3SJason Evans 
1545a4bd5210SJason Evans /******************************************************************************/
1546a4bd5210SJason Evans 
154782872ac0SJason Evans static void
15481f0a49e8SJason Evans arena_i_purge(tsdn_t *tsdn, unsigned arena_ind, bool all)
154982872ac0SJason Evans {
155082872ac0SJason Evans 
15511f0a49e8SJason Evans 	malloc_mutex_lock(tsdn, &ctl_mtx);
1552df0d881dSJason Evans 	{
1553df0d881dSJason Evans 		unsigned narenas = ctl_stats.narenas;
155482872ac0SJason Evans 
1555df0d881dSJason Evans 		if (arena_ind == narenas) {
155682872ac0SJason Evans 			unsigned i;
1557df0d881dSJason Evans 			VARIABLE_ARRAY(arena_t *, tarenas, narenas);
1558df0d881dSJason Evans 
1559df0d881dSJason Evans 			for (i = 0; i < narenas; i++)
15601f0a49e8SJason Evans 				tarenas[i] = arena_get(tsdn, i, false);
1561df0d881dSJason Evans 
1562df0d881dSJason Evans 			/*
1563df0d881dSJason Evans 			 * No further need to hold ctl_mtx, since narenas and
1564df0d881dSJason Evans 			 * tarenas contain everything needed below.
1565df0d881dSJason Evans 			 */
15661f0a49e8SJason Evans 			malloc_mutex_unlock(tsdn, &ctl_mtx);
1567df0d881dSJason Evans 
1568df0d881dSJason Evans 			for (i = 0; i < narenas; i++) {
156982872ac0SJason Evans 				if (tarenas[i] != NULL)
15701f0a49e8SJason Evans 					arena_purge(tsdn, tarenas[i], all);
157182872ac0SJason Evans 			}
157282872ac0SJason Evans 		} else {
1573df0d881dSJason Evans 			arena_t *tarena;
1574df0d881dSJason Evans 
1575df0d881dSJason Evans 			assert(arena_ind < narenas);
1576df0d881dSJason Evans 
15771f0a49e8SJason Evans 			tarena = arena_get(tsdn, arena_ind, false);
1578df0d881dSJason Evans 
1579df0d881dSJason Evans 			/* No further need to hold ctl_mtx. */
15801f0a49e8SJason Evans 			malloc_mutex_unlock(tsdn, &ctl_mtx);
1581df0d881dSJason Evans 
1582df0d881dSJason Evans 			if (tarena != NULL)
15831f0a49e8SJason Evans 				arena_purge(tsdn, tarena, all);
1584df0d881dSJason Evans 		}
158582872ac0SJason Evans 	}
158682872ac0SJason Evans }
158782872ac0SJason Evans 
158882872ac0SJason Evans static int
15891f0a49e8SJason Evans arena_i_purge_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
15901f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
159182872ac0SJason Evans {
159282872ac0SJason Evans 	int ret;
159382872ac0SJason Evans 
159482872ac0SJason Evans 	READONLY();
159582872ac0SJason Evans 	WRITEONLY();
15961f0a49e8SJason Evans 	arena_i_purge(tsd_tsdn(tsd), (unsigned)mib[1], true);
1597df0d881dSJason Evans 
1598df0d881dSJason Evans 	ret = 0;
1599df0d881dSJason Evans label_return:
1600df0d881dSJason Evans 	return (ret);
1601df0d881dSJason Evans }
1602df0d881dSJason Evans 
1603df0d881dSJason Evans static int
16041f0a49e8SJason Evans arena_i_decay_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
16051f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1606df0d881dSJason Evans {
1607df0d881dSJason Evans 	int ret;
1608df0d881dSJason Evans 
1609df0d881dSJason Evans 	READONLY();
1610df0d881dSJason Evans 	WRITEONLY();
16111f0a49e8SJason Evans 	arena_i_purge(tsd_tsdn(tsd), (unsigned)mib[1], false);
161282872ac0SJason Evans 
161382872ac0SJason Evans 	ret = 0;
161482872ac0SJason Evans label_return:
161582872ac0SJason Evans 	return (ret);
161682872ac0SJason Evans }
161782872ac0SJason Evans 
161882872ac0SJason Evans static int
16191f0a49e8SJason Evans arena_i_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
16201f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
16211f0a49e8SJason Evans {
16221f0a49e8SJason Evans 	int ret;
16231f0a49e8SJason Evans 	unsigned arena_ind;
16241f0a49e8SJason Evans 	arena_t *arena;
16251f0a49e8SJason Evans 
16261f0a49e8SJason Evans 	READONLY();
16271f0a49e8SJason Evans 	WRITEONLY();
16281f0a49e8SJason Evans 
16291f0a49e8SJason Evans 	if ((config_valgrind && unlikely(in_valgrind)) || (config_fill &&
16301f0a49e8SJason Evans 	    unlikely(opt_quarantine))) {
16311f0a49e8SJason Evans 		ret = EFAULT;
16321f0a49e8SJason Evans 		goto label_return;
16331f0a49e8SJason Evans 	}
16341f0a49e8SJason Evans 
16351f0a49e8SJason Evans 	arena_ind = (unsigned)mib[1];
16361f0a49e8SJason Evans 	if (config_debug) {
16371f0a49e8SJason Evans 		malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
16381f0a49e8SJason Evans 		assert(arena_ind < ctl_stats.narenas);
16391f0a49e8SJason Evans 		malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
16401f0a49e8SJason Evans 	}
16411f0a49e8SJason Evans 	assert(arena_ind >= opt_narenas);
16421f0a49e8SJason Evans 
16431f0a49e8SJason Evans 	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
16441f0a49e8SJason Evans 
16451f0a49e8SJason Evans 	arena_reset(tsd, arena);
16461f0a49e8SJason Evans 
16471f0a49e8SJason Evans 	ret = 0;
16481f0a49e8SJason Evans label_return:
16491f0a49e8SJason Evans 	return (ret);
16501f0a49e8SJason Evans }
16511f0a49e8SJason Evans 
16521f0a49e8SJason Evans static int
16531f0a49e8SJason Evans arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
16541f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
165582872ac0SJason Evans {
1656d0e79aa3SJason Evans 	int ret;
1657d0e79aa3SJason Evans 	const char *dss = NULL;
1658df0d881dSJason Evans 	unsigned arena_ind = (unsigned)mib[1];
165982872ac0SJason Evans 	dss_prec_t dss_prec_old = dss_prec_limit;
166082872ac0SJason Evans 	dss_prec_t dss_prec = dss_prec_limit;
166182872ac0SJason Evans 
16621f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
166382872ac0SJason Evans 	WRITE(dss, const char *);
1664d0e79aa3SJason Evans 	if (dss != NULL) {
1665d0e79aa3SJason Evans 		int i;
1666d0e79aa3SJason Evans 		bool match = false;
1667d0e79aa3SJason Evans 
166882872ac0SJason Evans 		for (i = 0; i < dss_prec_limit; i++) {
166982872ac0SJason Evans 			if (strcmp(dss_prec_names[i], dss) == 0) {
167082872ac0SJason Evans 				dss_prec = i;
167182872ac0SJason Evans 				match = true;
167282872ac0SJason Evans 				break;
167382872ac0SJason Evans 			}
167482872ac0SJason Evans 		}
1675d0e79aa3SJason Evans 
1676d0e79aa3SJason Evans 		if (!match) {
167782872ac0SJason Evans 			ret = EINVAL;
167882872ac0SJason Evans 			goto label_return;
167982872ac0SJason Evans 		}
1680d0e79aa3SJason Evans 	}
168182872ac0SJason Evans 
168282872ac0SJason Evans 	if (arena_ind < ctl_stats.narenas) {
16831f0a49e8SJason Evans 		arena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1684d0e79aa3SJason Evans 		if (arena == NULL || (dss_prec != dss_prec_limit &&
16851f0a49e8SJason Evans 		    arena_dss_prec_set(tsd_tsdn(tsd), arena, dss_prec))) {
1686d0e79aa3SJason Evans 			ret = EFAULT;
1687d0e79aa3SJason Evans 			goto label_return;
168882872ac0SJason Evans 		}
16891f0a49e8SJason Evans 		dss_prec_old = arena_dss_prec_get(tsd_tsdn(tsd), arena);
1690d0e79aa3SJason Evans 	} else {
1691d0e79aa3SJason Evans 		if (dss_prec != dss_prec_limit &&
1692bde95144SJason Evans 		    chunk_dss_prec_set(dss_prec)) {
1693d0e79aa3SJason Evans 			ret = EFAULT;
1694d0e79aa3SJason Evans 			goto label_return;
1695d0e79aa3SJason Evans 		}
1696bde95144SJason Evans 		dss_prec_old = chunk_dss_prec_get();
1697d0e79aa3SJason Evans 	}
1698d0e79aa3SJason Evans 
169982872ac0SJason Evans 	dss = dss_prec_names[dss_prec_old];
170082872ac0SJason Evans 	READ(dss, const char *);
1701d0e79aa3SJason Evans 
1702d0e79aa3SJason Evans 	ret = 0;
1703d0e79aa3SJason Evans label_return:
17041f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1705d0e79aa3SJason Evans 	return (ret);
1706d0e79aa3SJason Evans }
1707d0e79aa3SJason Evans 
1708d0e79aa3SJason Evans static int
17091f0a49e8SJason Evans arena_i_lg_dirty_mult_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
17101f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1711d0e79aa3SJason Evans {
1712d0e79aa3SJason Evans 	int ret;
1713df0d881dSJason Evans 	unsigned arena_ind = (unsigned)mib[1];
1714d0e79aa3SJason Evans 	arena_t *arena;
1715d0e79aa3SJason Evans 
17161f0a49e8SJason Evans 	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1717d0e79aa3SJason Evans 	if (arena == NULL) {
171882872ac0SJason Evans 		ret = EFAULT;
171982872ac0SJason Evans 		goto label_return;
172082872ac0SJason Evans 	}
172182872ac0SJason Evans 
1722d0e79aa3SJason Evans 	if (oldp != NULL && oldlenp != NULL) {
17231f0a49e8SJason Evans 		size_t oldval = arena_lg_dirty_mult_get(tsd_tsdn(tsd), arena);
1724d0e79aa3SJason Evans 		READ(oldval, ssize_t);
1725d0e79aa3SJason Evans 	}
1726d0e79aa3SJason Evans 	if (newp != NULL) {
1727d0e79aa3SJason Evans 		if (newlen != sizeof(ssize_t)) {
1728d0e79aa3SJason Evans 			ret = EINVAL;
1729d0e79aa3SJason Evans 			goto label_return;
1730d0e79aa3SJason Evans 		}
17311f0a49e8SJason Evans 		if (arena_lg_dirty_mult_set(tsd_tsdn(tsd), arena,
17321f0a49e8SJason Evans 		    *(ssize_t *)newp)) {
1733d0e79aa3SJason Evans 			ret = EFAULT;
1734d0e79aa3SJason Evans 			goto label_return;
1735d0e79aa3SJason Evans 		}
1736d0e79aa3SJason Evans 	}
1737d0e79aa3SJason Evans 
1738d0e79aa3SJason Evans 	ret = 0;
1739d0e79aa3SJason Evans label_return:
1740d0e79aa3SJason Evans 	return (ret);
1741d0e79aa3SJason Evans }
1742d0e79aa3SJason Evans 
1743d0e79aa3SJason Evans static int
17441f0a49e8SJason Evans arena_i_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1745df0d881dSJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1746df0d881dSJason Evans {
1747df0d881dSJason Evans 	int ret;
1748df0d881dSJason Evans 	unsigned arena_ind = (unsigned)mib[1];
1749df0d881dSJason Evans 	arena_t *arena;
1750df0d881dSJason Evans 
17511f0a49e8SJason Evans 	arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
1752df0d881dSJason Evans 	if (arena == NULL) {
1753df0d881dSJason Evans 		ret = EFAULT;
1754df0d881dSJason Evans 		goto label_return;
1755df0d881dSJason Evans 	}
1756df0d881dSJason Evans 
1757df0d881dSJason Evans 	if (oldp != NULL && oldlenp != NULL) {
17581f0a49e8SJason Evans 		size_t oldval = arena_decay_time_get(tsd_tsdn(tsd), arena);
1759df0d881dSJason Evans 		READ(oldval, ssize_t);
1760df0d881dSJason Evans 	}
1761df0d881dSJason Evans 	if (newp != NULL) {
1762df0d881dSJason Evans 		if (newlen != sizeof(ssize_t)) {
1763df0d881dSJason Evans 			ret = EINVAL;
1764df0d881dSJason Evans 			goto label_return;
1765df0d881dSJason Evans 		}
17661f0a49e8SJason Evans 		if (arena_decay_time_set(tsd_tsdn(tsd), arena,
17671f0a49e8SJason Evans 		    *(ssize_t *)newp)) {
1768df0d881dSJason Evans 			ret = EFAULT;
1769df0d881dSJason Evans 			goto label_return;
1770df0d881dSJason Evans 		}
1771df0d881dSJason Evans 	}
1772df0d881dSJason Evans 
1773df0d881dSJason Evans 	ret = 0;
1774df0d881dSJason Evans label_return:
1775df0d881dSJason Evans 	return (ret);
1776df0d881dSJason Evans }
1777df0d881dSJason Evans 
1778df0d881dSJason Evans static int
17791f0a49e8SJason Evans arena_i_chunk_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
17801f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1781d0e79aa3SJason Evans {
1782d0e79aa3SJason Evans 	int ret;
1783df0d881dSJason Evans 	unsigned arena_ind = (unsigned)mib[1];
1784d0e79aa3SJason Evans 	arena_t *arena;
1785d0e79aa3SJason Evans 
17861f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1787d0e79aa3SJason Evans 	if (arena_ind < narenas_total_get() && (arena =
17881f0a49e8SJason Evans 	    arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) {
1789d0e79aa3SJason Evans 		if (newp != NULL) {
1790d0e79aa3SJason Evans 			chunk_hooks_t old_chunk_hooks, new_chunk_hooks;
1791d0e79aa3SJason Evans 			WRITE(new_chunk_hooks, chunk_hooks_t);
17921f0a49e8SJason Evans 			old_chunk_hooks = chunk_hooks_set(tsd_tsdn(tsd), arena,
1793d0e79aa3SJason Evans 			    &new_chunk_hooks);
1794d0e79aa3SJason Evans 			READ(old_chunk_hooks, chunk_hooks_t);
1795d0e79aa3SJason Evans 		} else {
17961f0a49e8SJason Evans 			chunk_hooks_t old_chunk_hooks =
17971f0a49e8SJason Evans 			    chunk_hooks_get(tsd_tsdn(tsd), arena);
1798d0e79aa3SJason Evans 			READ(old_chunk_hooks, chunk_hooks_t);
1799d0e79aa3SJason Evans 		}
1800d0e79aa3SJason Evans 	} else {
1801d0e79aa3SJason Evans 		ret = EFAULT;
1802d0e79aa3SJason Evans 		goto label_return;
1803d0e79aa3SJason Evans 	}
180482872ac0SJason Evans 	ret = 0;
180582872ac0SJason Evans label_return:
18061f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
180782872ac0SJason Evans 	return (ret);
180882872ac0SJason Evans }
180982872ac0SJason Evans 
181082872ac0SJason Evans static const ctl_named_node_t *
18111f0a49e8SJason Evans arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
181282872ac0SJason Evans {
181382872ac0SJason Evans 	const ctl_named_node_t *ret;
181482872ac0SJason Evans 
18151f0a49e8SJason Evans 	malloc_mutex_lock(tsdn, &ctl_mtx);
181682872ac0SJason Evans 	if (i > ctl_stats.narenas) {
181782872ac0SJason Evans 		ret = NULL;
181882872ac0SJason Evans 		goto label_return;
181982872ac0SJason Evans 	}
182082872ac0SJason Evans 
182182872ac0SJason Evans 	ret = super_arena_i_node;
182282872ac0SJason Evans label_return:
18231f0a49e8SJason Evans 	malloc_mutex_unlock(tsdn, &ctl_mtx);
182482872ac0SJason Evans 	return (ret);
182582872ac0SJason Evans }
182682872ac0SJason Evans 
182782872ac0SJason Evans /******************************************************************************/
182882872ac0SJason Evans 
182982872ac0SJason Evans static int
18301f0a49e8SJason Evans arenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
183182872ac0SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
183282872ac0SJason Evans {
183382872ac0SJason Evans 	int ret;
183482872ac0SJason Evans 	unsigned narenas;
183582872ac0SJason Evans 
18361f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
183782872ac0SJason Evans 	READONLY();
183882872ac0SJason Evans 	if (*oldlenp != sizeof(unsigned)) {
183982872ac0SJason Evans 		ret = EINVAL;
184082872ac0SJason Evans 		goto label_return;
184182872ac0SJason Evans 	}
184282872ac0SJason Evans 	narenas = ctl_stats.narenas;
184382872ac0SJason Evans 	READ(narenas, unsigned);
184482872ac0SJason Evans 
184582872ac0SJason Evans 	ret = 0;
184682872ac0SJason Evans label_return:
18471f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
184882872ac0SJason Evans 	return (ret);
184982872ac0SJason Evans }
1850a4bd5210SJason Evans 
1851a4bd5210SJason Evans static int
18521f0a49e8SJason Evans arenas_initialized_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1853a4bd5210SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1854a4bd5210SJason Evans {
1855a4bd5210SJason Evans 	int ret;
1856a4bd5210SJason Evans 	unsigned nread, i;
1857a4bd5210SJason Evans 
18581f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1859a4bd5210SJason Evans 	READONLY();
186082872ac0SJason Evans 	if (*oldlenp != ctl_stats.narenas * sizeof(bool)) {
1861a4bd5210SJason Evans 		ret = EINVAL;
186282872ac0SJason Evans 		nread = (*oldlenp < ctl_stats.narenas * sizeof(bool))
1863df0d881dSJason Evans 		    ? (unsigned)(*oldlenp / sizeof(bool)) : ctl_stats.narenas;
1864a4bd5210SJason Evans 	} else {
1865a4bd5210SJason Evans 		ret = 0;
186682872ac0SJason Evans 		nread = ctl_stats.narenas;
1867a4bd5210SJason Evans 	}
1868a4bd5210SJason Evans 
1869a4bd5210SJason Evans 	for (i = 0; i < nread; i++)
1870a4bd5210SJason Evans 		((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
1871a4bd5210SJason Evans 
1872a4bd5210SJason Evans label_return:
18731f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1874a4bd5210SJason Evans 	return (ret);
1875a4bd5210SJason Evans }
1876a4bd5210SJason Evans 
1877d0e79aa3SJason Evans static int
18781f0a49e8SJason Evans arenas_lg_dirty_mult_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
18791f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
1880d0e79aa3SJason Evans {
1881d0e79aa3SJason Evans 	int ret;
1882d0e79aa3SJason Evans 
1883d0e79aa3SJason Evans 	if (oldp != NULL && oldlenp != NULL) {
1884d0e79aa3SJason Evans 		size_t oldval = arena_lg_dirty_mult_default_get();
1885d0e79aa3SJason Evans 		READ(oldval, ssize_t);
1886d0e79aa3SJason Evans 	}
1887d0e79aa3SJason Evans 	if (newp != NULL) {
1888d0e79aa3SJason Evans 		if (newlen != sizeof(ssize_t)) {
1889d0e79aa3SJason Evans 			ret = EINVAL;
1890d0e79aa3SJason Evans 			goto label_return;
1891d0e79aa3SJason Evans 		}
1892d0e79aa3SJason Evans 		if (arena_lg_dirty_mult_default_set(*(ssize_t *)newp)) {
1893d0e79aa3SJason Evans 			ret = EFAULT;
1894d0e79aa3SJason Evans 			goto label_return;
1895d0e79aa3SJason Evans 		}
1896d0e79aa3SJason Evans 	}
1897d0e79aa3SJason Evans 
1898d0e79aa3SJason Evans 	ret = 0;
1899d0e79aa3SJason Evans label_return:
1900d0e79aa3SJason Evans 	return (ret);
1901d0e79aa3SJason Evans }
1902d0e79aa3SJason Evans 
1903df0d881dSJason Evans static int
19041f0a49e8SJason Evans arenas_decay_time_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1905df0d881dSJason Evans     size_t *oldlenp, void *newp, size_t newlen)
1906df0d881dSJason Evans {
1907df0d881dSJason Evans 	int ret;
1908df0d881dSJason Evans 
1909df0d881dSJason Evans 	if (oldp != NULL && oldlenp != NULL) {
1910df0d881dSJason Evans 		size_t oldval = arena_decay_time_default_get();
1911df0d881dSJason Evans 		READ(oldval, ssize_t);
1912df0d881dSJason Evans 	}
1913df0d881dSJason Evans 	if (newp != NULL) {
1914df0d881dSJason Evans 		if (newlen != sizeof(ssize_t)) {
1915df0d881dSJason Evans 			ret = EINVAL;
1916df0d881dSJason Evans 			goto label_return;
1917df0d881dSJason Evans 		}
1918df0d881dSJason Evans 		if (arena_decay_time_default_set(*(ssize_t *)newp)) {
1919df0d881dSJason Evans 			ret = EFAULT;
1920df0d881dSJason Evans 			goto label_return;
1921df0d881dSJason Evans 		}
1922df0d881dSJason Evans 	}
1923df0d881dSJason Evans 
1924df0d881dSJason Evans 	ret = 0;
1925df0d881dSJason Evans label_return:
1926df0d881dSJason Evans 	return (ret);
1927df0d881dSJason Evans }
1928df0d881dSJason Evans 
1929a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
1930a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_page, PAGE, size_t)
1931a4bd5210SJason Evans CTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)
1932a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)
1933a4bd5210SJason Evans CTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)
1934f921d10fSJason Evans CTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)
1935f921d10fSJason Evans CTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)
1936f921d10fSJason Evans CTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)
1937f921d10fSJason Evans static const ctl_named_node_t *
19381f0a49e8SJason Evans arenas_bin_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1939f921d10fSJason Evans {
1940f921d10fSJason Evans 
1941f921d10fSJason Evans 	if (i > NBINS)
1942f921d10fSJason Evans 		return (NULL);
1943f921d10fSJason Evans 	return (super_arenas_bin_i_node);
1944f921d10fSJason Evans }
1945f921d10fSJason Evans 
1946d0e79aa3SJason Evans CTL_RO_NL_GEN(arenas_nlruns, nlclasses, unsigned)
1947df0d881dSJason Evans CTL_RO_NL_GEN(arenas_lrun_i_size, index2size(NBINS+(szind_t)mib[2]), size_t)
1948f921d10fSJason Evans static const ctl_named_node_t *
19491f0a49e8SJason Evans arenas_lrun_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1950f921d10fSJason Evans {
1951f921d10fSJason Evans 
1952f921d10fSJason Evans 	if (i > nlclasses)
1953f921d10fSJason Evans 		return (NULL);
1954f921d10fSJason Evans 	return (super_arenas_lrun_i_node);
1955f921d10fSJason Evans }
1956a4bd5210SJason Evans 
1957d0e79aa3SJason Evans CTL_RO_NL_GEN(arenas_nhchunks, nhclasses, unsigned)
1958df0d881dSJason Evans CTL_RO_NL_GEN(arenas_hchunk_i_size, index2size(NBINS+nlclasses+(szind_t)mib[2]),
1959df0d881dSJason Evans     size_t)
1960d0e79aa3SJason Evans static const ctl_named_node_t *
19611f0a49e8SJason Evans arenas_hchunk_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
1962a4bd5210SJason Evans {
1963a4bd5210SJason Evans 
1964d0e79aa3SJason Evans 	if (i > nhclasses)
1965d0e79aa3SJason Evans 		return (NULL);
1966d0e79aa3SJason Evans 	return (super_arenas_hchunk_i_node);
196782872ac0SJason Evans }
196882872ac0SJason Evans 
196982872ac0SJason Evans static int
19701f0a49e8SJason Evans arenas_extend_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
19711f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
197282872ac0SJason Evans {
197382872ac0SJason Evans 	int ret;
197488ad2f8dSJason Evans 	unsigned narenas;
197582872ac0SJason Evans 
19761f0a49e8SJason Evans 	malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
197782872ac0SJason Evans 	READONLY();
19781f0a49e8SJason Evans 	if (ctl_grow(tsd_tsdn(tsd))) {
197982872ac0SJason Evans 		ret = EAGAIN;
1980a4bd5210SJason Evans 		goto label_return;
1981a4bd5210SJason Evans 	}
198288ad2f8dSJason Evans 	narenas = ctl_stats.narenas - 1;
198388ad2f8dSJason Evans 	READ(narenas, unsigned);
1984a4bd5210SJason Evans 
1985a4bd5210SJason Evans 	ret = 0;
1986a4bd5210SJason Evans label_return:
19871f0a49e8SJason Evans 	malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1988a4bd5210SJason Evans 	return (ret);
1989a4bd5210SJason Evans }
1990a4bd5210SJason Evans 
1991a4bd5210SJason Evans /******************************************************************************/
1992a4bd5210SJason Evans 
1993a4bd5210SJason Evans static int
19941f0a49e8SJason Evans prof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
19951f0a49e8SJason Evans     void *oldp, size_t *oldlenp, void *newp, size_t newlen)
19961f0a49e8SJason Evans {
19971f0a49e8SJason Evans 	int ret;
19981f0a49e8SJason Evans 	bool oldval;
19991f0a49e8SJason Evans 
20001f0a49e8SJason Evans 	if (!config_prof)
20011f0a49e8SJason Evans 		return (ENOENT);
20021f0a49e8SJason Evans 
20031f0a49e8SJason Evans 	if (newp != NULL) {
20041f0a49e8SJason Evans 		if (newlen != sizeof(bool)) {
20051f0a49e8SJason Evans 			ret = EINVAL;
20061f0a49e8SJason Evans 			goto label_return;
20071f0a49e8SJason Evans 		}
20081f0a49e8SJason Evans 		oldval = prof_thread_active_init_set(tsd_tsdn(tsd),
20091f0a49e8SJason Evans 		    *(bool *)newp);
20101f0a49e8SJason Evans 	} else
20111f0a49e8SJason Evans 		oldval = prof_thread_active_init_get(tsd_tsdn(tsd));
20121f0a49e8SJason Evans 	READ(oldval, bool);
20131f0a49e8SJason Evans 
20141f0a49e8SJason Evans 	ret = 0;
20151f0a49e8SJason Evans label_return:
20161f0a49e8SJason Evans 	return (ret);
20171f0a49e8SJason Evans }
20181f0a49e8SJason Evans 
20191f0a49e8SJason Evans static int
20201f0a49e8SJason Evans prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2021d0e79aa3SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
2022d0e79aa3SJason Evans {
2023d0e79aa3SJason Evans 	int ret;
2024d0e79aa3SJason Evans 	bool oldval;
2025d0e79aa3SJason Evans 
2026d0e79aa3SJason Evans 	if (!config_prof)
2027d0e79aa3SJason Evans 		return (ENOENT);
2028d0e79aa3SJason Evans 
2029d0e79aa3SJason Evans 	if (newp != NULL) {
2030d0e79aa3SJason Evans 		if (newlen != sizeof(bool)) {
2031d0e79aa3SJason Evans 			ret = EINVAL;
2032d0e79aa3SJason Evans 			goto label_return;
2033d0e79aa3SJason Evans 		}
20341f0a49e8SJason Evans 		oldval = prof_active_set(tsd_tsdn(tsd), *(bool *)newp);
2035d0e79aa3SJason Evans 	} else
20361f0a49e8SJason Evans 		oldval = prof_active_get(tsd_tsdn(tsd));
2037d0e79aa3SJason Evans 	READ(oldval, bool);
2038d0e79aa3SJason Evans 
2039d0e79aa3SJason Evans 	ret = 0;
2040d0e79aa3SJason Evans label_return:
2041d0e79aa3SJason Evans 	return (ret);
2042d0e79aa3SJason Evans }
2043d0e79aa3SJason Evans 
2044d0e79aa3SJason Evans static int
20451f0a49e8SJason Evans prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
20461f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
2047a4bd5210SJason Evans {
2048a4bd5210SJason Evans 	int ret;
2049a4bd5210SJason Evans 	const char *filename = NULL;
2050a4bd5210SJason Evans 
2051d0e79aa3SJason Evans 	if (!config_prof)
2052a4bd5210SJason Evans 		return (ENOENT);
2053a4bd5210SJason Evans 
2054a4bd5210SJason Evans 	WRITEONLY();
2055a4bd5210SJason Evans 	WRITE(filename, const char *);
2056a4bd5210SJason Evans 
20571f0a49e8SJason Evans 	if (prof_mdump(tsd, filename)) {
2058a4bd5210SJason Evans 		ret = EFAULT;
2059a4bd5210SJason Evans 		goto label_return;
2060a4bd5210SJason Evans 	}
2061a4bd5210SJason Evans 
2062a4bd5210SJason Evans 	ret = 0;
2063a4bd5210SJason Evans label_return:
2064a4bd5210SJason Evans 	return (ret);
2065a4bd5210SJason Evans }
2066a4bd5210SJason Evans 
2067d0e79aa3SJason Evans static int
20681f0a49e8SJason Evans prof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
20691f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
2070d0e79aa3SJason Evans {
2071d0e79aa3SJason Evans 	int ret;
2072d0e79aa3SJason Evans 	bool oldval;
2073d0e79aa3SJason Evans 
2074d0e79aa3SJason Evans 	if (!config_prof)
2075d0e79aa3SJason Evans 		return (ENOENT);
2076d0e79aa3SJason Evans 
2077d0e79aa3SJason Evans 	if (newp != NULL) {
2078d0e79aa3SJason Evans 		if (newlen != sizeof(bool)) {
2079d0e79aa3SJason Evans 			ret = EINVAL;
2080d0e79aa3SJason Evans 			goto label_return;
2081d0e79aa3SJason Evans 		}
20821f0a49e8SJason Evans 		oldval = prof_gdump_set(tsd_tsdn(tsd), *(bool *)newp);
2083d0e79aa3SJason Evans 	} else
20841f0a49e8SJason Evans 		oldval = prof_gdump_get(tsd_tsdn(tsd));
2085d0e79aa3SJason Evans 	READ(oldval, bool);
2086d0e79aa3SJason Evans 
2087d0e79aa3SJason Evans 	ret = 0;
2088d0e79aa3SJason Evans label_return:
2089d0e79aa3SJason Evans 	return (ret);
2090d0e79aa3SJason Evans }
2091d0e79aa3SJason Evans 
2092d0e79aa3SJason Evans static int
20931f0a49e8SJason Evans prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
20941f0a49e8SJason Evans     size_t *oldlenp, void *newp, size_t newlen)
2095d0e79aa3SJason Evans {
2096d0e79aa3SJason Evans 	int ret;
2097d0e79aa3SJason Evans 	size_t lg_sample = lg_prof_sample;
2098d0e79aa3SJason Evans 
2099d0e79aa3SJason Evans 	if (!config_prof)
2100d0e79aa3SJason Evans 		return (ENOENT);
2101d0e79aa3SJason Evans 
2102d0e79aa3SJason Evans 	WRITEONLY();
2103d0e79aa3SJason Evans 	WRITE(lg_sample, size_t);
2104d0e79aa3SJason Evans 	if (lg_sample >= (sizeof(uint64_t) << 3))
2105d0e79aa3SJason Evans 		lg_sample = (sizeof(uint64_t) << 3) - 1;
2106d0e79aa3SJason Evans 
2107bde95144SJason Evans 	prof_reset(tsd, lg_sample);
2108d0e79aa3SJason Evans 
2109d0e79aa3SJason Evans 	ret = 0;
2110d0e79aa3SJason Evans label_return:
2111d0e79aa3SJason Evans 	return (ret);
2112d0e79aa3SJason Evans }
2113d0e79aa3SJason Evans 
2114a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
2115d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t)
2116a4bd5210SJason Evans 
2117a4bd5210SJason Evans /******************************************************************************/
2118a4bd5210SJason Evans 
2119f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)
2120f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)
2121f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
2122d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_metadata, ctl_stats.metadata, size_t)
2123d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_resident, ctl_stats.resident, size_t)
2124f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)
21251f0a49e8SJason Evans CTL_RO_CGEN(config_stats, stats_retained, ctl_stats.retained, size_t)
2126f921d10fSJason Evans 
2127f921d10fSJason Evans CTL_RO_GEN(stats_arenas_i_dss, ctl_stats.arenas[mib[2]].dss, const char *)
2128d0e79aa3SJason Evans CTL_RO_GEN(stats_arenas_i_lg_dirty_mult, ctl_stats.arenas[mib[2]].lg_dirty_mult,
2129d0e79aa3SJason Evans     ssize_t)
2130df0d881dSJason Evans CTL_RO_GEN(stats_arenas_i_decay_time, ctl_stats.arenas[mib[2]].decay_time,
2131df0d881dSJason Evans     ssize_t)
2132f921d10fSJason Evans CTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)
2133f921d10fSJason Evans CTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
2134f921d10fSJason Evans CTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
2135f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
2136f921d10fSJason Evans     ctl_stats.arenas[mib[2]].astats.mapped, size_t)
21371f0a49e8SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_retained,
21381f0a49e8SJason Evans     ctl_stats.arenas[mib[2]].astats.retained, size_t)
2139f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
2140f921d10fSJason Evans     ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
2141f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
2142f921d10fSJason Evans     ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)
2143f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_purged,
2144f921d10fSJason Evans     ctl_stats.arenas[mib[2]].astats.purged, uint64_t)
2145d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_mapped,
2146d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.metadata_mapped, size_t)
2147d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_allocated,
2148d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.metadata_allocated, size_t)
2149f921d10fSJason Evans 
2150a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
2151a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].allocated_small, size_t)
2152a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
2153a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)
2154a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
2155a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)
2156a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
2157a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)
2158a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
2159a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)
2160a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
2161a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)
2162a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
2163a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)
2164a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
2165a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)
2166d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_huge_allocated,
2167d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.allocated_huge, size_t)
2168d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_huge_nmalloc,
2169d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t)
2170d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_huge_ndalloc,
2171d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.ndalloc_huge, uint64_t)
2172d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_huge_nrequests,
2173d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].astats.nmalloc_huge, uint64_t) /* Intentional. */
2174a4bd5210SJason Evans 
2175a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
2176a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)
2177a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
2178a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)
2179a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
2180a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)
2181d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curregs,
2182d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].curregs, size_t)
2183a4bd5210SJason Evans CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,
2184a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)
2185a4bd5210SJason Evans CTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,
2186a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)
2187a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,
2188a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)
2189a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,
2190a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)
2191a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,
2192a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)
2193a4bd5210SJason Evans 
219482872ac0SJason Evans static const ctl_named_node_t *
21951f0a49e8SJason Evans stats_arenas_i_bins_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
21961f0a49e8SJason Evans     size_t j)
2197a4bd5210SJason Evans {
2198a4bd5210SJason Evans 
2199a4bd5210SJason Evans 	if (j > NBINS)
2200a4bd5210SJason Evans 		return (NULL);
2201a4bd5210SJason Evans 	return (super_stats_arenas_i_bins_j_node);
2202a4bd5210SJason Evans }
2203a4bd5210SJason Evans 
2204a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,
2205a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)
2206a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,
2207a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)
2208a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,
2209a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)
2210a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,
2211a4bd5210SJason Evans     ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)
2212a4bd5210SJason Evans 
221382872ac0SJason Evans static const ctl_named_node_t *
22141f0a49e8SJason Evans stats_arenas_i_lruns_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
22151f0a49e8SJason Evans     size_t j)
2216a4bd5210SJason Evans {
2217a4bd5210SJason Evans 
2218a4bd5210SJason Evans 	if (j > nlclasses)
2219a4bd5210SJason Evans 		return (NULL);
2220a4bd5210SJason Evans 	return (super_stats_arenas_i_lruns_j_node);
2221a4bd5210SJason Evans }
2222a4bd5210SJason Evans 
2223d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nmalloc,
2224d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, uint64_t)
2225d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_ndalloc,
2226d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].hstats[mib[4]].ndalloc, uint64_t)
2227d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_nrequests,
2228d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].hstats[mib[4]].nmalloc, /* Intentional. */
2229d0e79aa3SJason Evans     uint64_t)
2230d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_hchunks_j_curhchunks,
2231d0e79aa3SJason Evans     ctl_stats.arenas[mib[2]].hstats[mib[4]].curhchunks, size_t)
2232d0e79aa3SJason Evans 
2233d0e79aa3SJason Evans static const ctl_named_node_t *
22341f0a49e8SJason Evans stats_arenas_i_hchunks_j_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
22351f0a49e8SJason Evans     size_t j)
2236d0e79aa3SJason Evans {
2237d0e79aa3SJason Evans 
2238d0e79aa3SJason Evans 	if (j > nhclasses)
2239d0e79aa3SJason Evans 		return (NULL);
2240d0e79aa3SJason Evans 	return (super_stats_arenas_i_hchunks_j_node);
2241d0e79aa3SJason Evans }
2242d0e79aa3SJason Evans 
224382872ac0SJason Evans static const ctl_named_node_t *
22441f0a49e8SJason Evans stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen, size_t i)
2245a4bd5210SJason Evans {
2246e722f8f8SJason Evans 	const ctl_named_node_t * ret;
2247a4bd5210SJason Evans 
22481f0a49e8SJason Evans 	malloc_mutex_lock(tsdn, &ctl_mtx);
2249d0e79aa3SJason Evans 	if (i > ctl_stats.narenas || !ctl_stats.arenas[i].initialized) {
2250a4bd5210SJason Evans 		ret = NULL;
2251a4bd5210SJason Evans 		goto label_return;
2252a4bd5210SJason Evans 	}
2253a4bd5210SJason Evans 
2254a4bd5210SJason Evans 	ret = super_stats_arenas_i_node;
2255a4bd5210SJason Evans label_return:
22561f0a49e8SJason Evans 	malloc_mutex_unlock(tsdn, &ctl_mtx);
2257a4bd5210SJason Evans 	return (ret);
2258a4bd5210SJason Evans }
2259