ctl.c revision 235238
1234370Sjasone#define	JEMALLOC_CTL_C_
2234370Sjasone#include "jemalloc/internal/jemalloc_internal.h"
3234370Sjasone
4234370Sjasone/******************************************************************************/
5234370Sjasone/* Data. */
6234370Sjasone
7234370Sjasone/*
8234370Sjasone * ctl_mtx protects the following:
9234370Sjasone * - ctl_stats.*
10234370Sjasone * - opt_prof_active
11234370Sjasone */
12234370Sjasonestatic malloc_mutex_t	ctl_mtx;
13234370Sjasonestatic bool		ctl_initialized;
14234370Sjasonestatic uint64_t		ctl_epoch;
15234370Sjasonestatic ctl_stats_t	ctl_stats;
16234370Sjasone
17234370Sjasone/******************************************************************************/
18235238Sjasone/* Helpers for named and indexed nodes. */
19235238Sjasone
20235238Sjasonestatic inline const ctl_named_node_t *
21235238Sjasonectl_named_node(const ctl_node_t *node)
22235238Sjasone{
23235238Sjasone
24235238Sjasone	return ((node->named) ? (const ctl_named_node_t *)node : NULL);
25235238Sjasone}
26235238Sjasone
27235238Sjasonestatic inline const ctl_named_node_t *
28235238Sjasonectl_named_children(const ctl_named_node_t *node, int index)
29235238Sjasone{
30235238Sjasone	const ctl_named_node_t *children = ctl_named_node(node->children);
31235238Sjasone
32235238Sjasone	return (children ? &children[index] : NULL);
33235238Sjasone}
34235238Sjasone
35235238Sjasonestatic inline const ctl_indexed_node_t *
36235238Sjasonectl_indexed_node(const ctl_node_t *node)
37235238Sjasone{
38235238Sjasone
39235238Sjasone	return ((node->named == false) ? (const ctl_indexed_node_t *)node :
40235238Sjasone	    NULL);
41235238Sjasone}
42235238Sjasone
43235238Sjasone/******************************************************************************/
44234370Sjasone/* Function prototypes for non-inline static functions. */
45234370Sjasone
46234370Sjasone#define	CTL_PROTO(n)							\
47234370Sjasonestatic int	n##_ctl(const size_t *mib, size_t miblen, void *oldp,	\
48234370Sjasone    size_t *oldlenp, void *newp, size_t newlen);
49234370Sjasone
50234370Sjasone#define	INDEX_PROTO(n)							\
51235238Sjasoneconst ctl_named_node_t	*n##_index(const size_t *mib, size_t miblen,	\
52234370Sjasone    size_t i);
53234370Sjasone
54234370Sjasonestatic bool	ctl_arena_init(ctl_arena_stats_t *astats);
55234370Sjasonestatic void	ctl_arena_clear(ctl_arena_stats_t *astats);
56234370Sjasonestatic void	ctl_arena_stats_amerge(ctl_arena_stats_t *cstats,
57234370Sjasone    arena_t *arena);
58234370Sjasonestatic void	ctl_arena_stats_smerge(ctl_arena_stats_t *sstats,
59234370Sjasone    ctl_arena_stats_t *astats);
60234370Sjasonestatic void	ctl_arena_refresh(arena_t *arena, unsigned i);
61234370Sjasonestatic void	ctl_refresh(void);
62234370Sjasonestatic bool	ctl_init(void);
63234370Sjasonestatic int	ctl_lookup(const char *name, ctl_node_t const **nodesp,
64234370Sjasone    size_t *mibp, size_t *depthp);
65234370Sjasone
66234370SjasoneCTL_PROTO(version)
67234370SjasoneCTL_PROTO(epoch)
68234370SjasoneCTL_PROTO(thread_tcache_enabled)
69234370SjasoneCTL_PROTO(thread_tcache_flush)
70234370SjasoneCTL_PROTO(thread_arena)
71234370SjasoneCTL_PROTO(thread_allocated)
72234370SjasoneCTL_PROTO(thread_allocatedp)
73234370SjasoneCTL_PROTO(thread_deallocated)
74234370SjasoneCTL_PROTO(thread_deallocatedp)
75234370SjasoneCTL_PROTO(config_debug)
76234370SjasoneCTL_PROTO(config_dss)
77234370SjasoneCTL_PROTO(config_fill)
78234370SjasoneCTL_PROTO(config_lazy_lock)
79235238SjasoneCTL_PROTO(config_mremap)
80234370SjasoneCTL_PROTO(config_munmap)
81234370SjasoneCTL_PROTO(config_prof)
82234370SjasoneCTL_PROTO(config_prof_libgcc)
83234370SjasoneCTL_PROTO(config_prof_libunwind)
84234370SjasoneCTL_PROTO(config_stats)
85234370SjasoneCTL_PROTO(config_tcache)
86234370SjasoneCTL_PROTO(config_tls)
87234370SjasoneCTL_PROTO(config_utrace)
88234370SjasoneCTL_PROTO(config_valgrind)
89234370SjasoneCTL_PROTO(config_xmalloc)
90234370SjasoneCTL_PROTO(opt_abort)
91234370SjasoneCTL_PROTO(opt_lg_chunk)
92234370SjasoneCTL_PROTO(opt_narenas)
93234370SjasoneCTL_PROTO(opt_lg_dirty_mult)
94234370SjasoneCTL_PROTO(opt_stats_print)
95234370SjasoneCTL_PROTO(opt_junk)
96234370SjasoneCTL_PROTO(opt_zero)
97234370SjasoneCTL_PROTO(opt_quarantine)
98234370SjasoneCTL_PROTO(opt_redzone)
99234370SjasoneCTL_PROTO(opt_utrace)
100234370SjasoneCTL_PROTO(opt_valgrind)
101234370SjasoneCTL_PROTO(opt_xmalloc)
102234370SjasoneCTL_PROTO(opt_tcache)
103234370SjasoneCTL_PROTO(opt_lg_tcache_max)
104234370SjasoneCTL_PROTO(opt_prof)
105234370SjasoneCTL_PROTO(opt_prof_prefix)
106234370SjasoneCTL_PROTO(opt_prof_active)
107234370SjasoneCTL_PROTO(opt_lg_prof_sample)
108234370SjasoneCTL_PROTO(opt_lg_prof_interval)
109234370SjasoneCTL_PROTO(opt_prof_gdump)
110234543SjasoneCTL_PROTO(opt_prof_final)
111234370SjasoneCTL_PROTO(opt_prof_leak)
112234370SjasoneCTL_PROTO(opt_prof_accum)
113234370SjasoneCTL_PROTO(arenas_bin_i_size)
114234370SjasoneCTL_PROTO(arenas_bin_i_nregs)
115234370SjasoneCTL_PROTO(arenas_bin_i_run_size)
116234370SjasoneINDEX_PROTO(arenas_bin_i)
117234370SjasoneCTL_PROTO(arenas_lrun_i_size)
118234370SjasoneINDEX_PROTO(arenas_lrun_i)
119234370SjasoneCTL_PROTO(arenas_narenas)
120234370SjasoneCTL_PROTO(arenas_initialized)
121234370SjasoneCTL_PROTO(arenas_quantum)
122234370SjasoneCTL_PROTO(arenas_page)
123234370SjasoneCTL_PROTO(arenas_tcache_max)
124234370SjasoneCTL_PROTO(arenas_nbins)
125234370SjasoneCTL_PROTO(arenas_nhbins)
126234370SjasoneCTL_PROTO(arenas_nlruns)
127234370SjasoneCTL_PROTO(arenas_purge)
128234370SjasoneCTL_PROTO(prof_active)
129234370SjasoneCTL_PROTO(prof_dump)
130234370SjasoneCTL_PROTO(prof_interval)
131234370SjasoneCTL_PROTO(stats_chunks_current)
132234370SjasoneCTL_PROTO(stats_chunks_total)
133234370SjasoneCTL_PROTO(stats_chunks_high)
134234370SjasoneCTL_PROTO(stats_huge_allocated)
135234370SjasoneCTL_PROTO(stats_huge_nmalloc)
136234370SjasoneCTL_PROTO(stats_huge_ndalloc)
137234370SjasoneCTL_PROTO(stats_arenas_i_small_allocated)
138234370SjasoneCTL_PROTO(stats_arenas_i_small_nmalloc)
139234370SjasoneCTL_PROTO(stats_arenas_i_small_ndalloc)
140234370SjasoneCTL_PROTO(stats_arenas_i_small_nrequests)
141234370SjasoneCTL_PROTO(stats_arenas_i_large_allocated)
142234370SjasoneCTL_PROTO(stats_arenas_i_large_nmalloc)
143234370SjasoneCTL_PROTO(stats_arenas_i_large_ndalloc)
144234370SjasoneCTL_PROTO(stats_arenas_i_large_nrequests)
145234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_allocated)
146234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nmalloc)
147234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_ndalloc)
148234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nrequests)
149234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nfills)
150234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nflushes)
151234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nruns)
152234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_nreruns)
153234370SjasoneCTL_PROTO(stats_arenas_i_bins_j_curruns)
154234370SjasoneINDEX_PROTO(stats_arenas_i_bins_j)
155234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_nmalloc)
156234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_ndalloc)
157234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_nrequests)
158234370SjasoneCTL_PROTO(stats_arenas_i_lruns_j_curruns)
159234370SjasoneINDEX_PROTO(stats_arenas_i_lruns_j)
160234370SjasoneCTL_PROTO(stats_arenas_i_nthreads)
161234370SjasoneCTL_PROTO(stats_arenas_i_pactive)
162234370SjasoneCTL_PROTO(stats_arenas_i_pdirty)
163234370SjasoneCTL_PROTO(stats_arenas_i_mapped)
164234370SjasoneCTL_PROTO(stats_arenas_i_npurge)
165234370SjasoneCTL_PROTO(stats_arenas_i_nmadvise)
166234370SjasoneCTL_PROTO(stats_arenas_i_purged)
167234370SjasoneINDEX_PROTO(stats_arenas_i)
168234370SjasoneCTL_PROTO(stats_cactive)
169234370SjasoneCTL_PROTO(stats_allocated)
170234370SjasoneCTL_PROTO(stats_active)
171234370SjasoneCTL_PROTO(stats_mapped)
172234370Sjasone
173234370Sjasone/******************************************************************************/
174234370Sjasone/* mallctl tree. */
175234370Sjasone
176234370Sjasone/* Maximum tree depth. */
177234370Sjasone#define	CTL_MAX_DEPTH	6
178234370Sjasone
179235238Sjasone#define	NAME(n)	{true},	n
180235238Sjasone#define	CHILD(t, c)							\
181235238Sjasone	sizeof(c##_node) / sizeof(ctl_##t##_node_t),			\
182235238Sjasone	(ctl_node_t *)c##_node,						\
183235238Sjasone	NULL
184235238Sjasone#define	CTL(c)	0, NULL, c##_ctl
185234370Sjasone
186234370Sjasone/*
187234370Sjasone * Only handles internal indexed nodes, since there are currently no external
188234370Sjasone * ones.
189234370Sjasone */
190235238Sjasone#define	INDEX(i)	{false},	i##_index
191234370Sjasone
192235238Sjasonestatic const ctl_named_node_t	tcache_node[] = {
193234370Sjasone	{NAME("enabled"),	CTL(thread_tcache_enabled)},
194234370Sjasone	{NAME("flush"),		CTL(thread_tcache_flush)}
195234370Sjasone};
196234370Sjasone
197235238Sjasonestatic const ctl_named_node_t	thread_node[] = {
198234370Sjasone	{NAME("arena"),		CTL(thread_arena)},
199234370Sjasone	{NAME("allocated"),	CTL(thread_allocated)},
200234370Sjasone	{NAME("allocatedp"),	CTL(thread_allocatedp)},
201234370Sjasone	{NAME("deallocated"),	CTL(thread_deallocated)},
202234370Sjasone	{NAME("deallocatedp"),	CTL(thread_deallocatedp)},
203235238Sjasone	{NAME("tcache"),	CHILD(named, tcache)}
204234370Sjasone};
205234370Sjasone
206235238Sjasonestatic const ctl_named_node_t	config_node[] = {
207234370Sjasone	{NAME("debug"),			CTL(config_debug)},
208234370Sjasone	{NAME("dss"),			CTL(config_dss)},
209234370Sjasone	{NAME("fill"),			CTL(config_fill)},
210234370Sjasone	{NAME("lazy_lock"),		CTL(config_lazy_lock)},
211235238Sjasone	{NAME("mremap"),		CTL(config_mremap)},
212234370Sjasone	{NAME("munmap"),		CTL(config_munmap)},
213234370Sjasone	{NAME("prof"),			CTL(config_prof)},
214234370Sjasone	{NAME("prof_libgcc"),		CTL(config_prof_libgcc)},
215234370Sjasone	{NAME("prof_libunwind"),	CTL(config_prof_libunwind)},
216234370Sjasone	{NAME("stats"),			CTL(config_stats)},
217234370Sjasone	{NAME("tcache"),		CTL(config_tcache)},
218234370Sjasone	{NAME("tls"),			CTL(config_tls)},
219234370Sjasone	{NAME("utrace"),		CTL(config_utrace)},
220234370Sjasone	{NAME("valgrind"),		CTL(config_valgrind)},
221234370Sjasone	{NAME("xmalloc"),		CTL(config_xmalloc)}
222234370Sjasone};
223234370Sjasone
224235238Sjasonestatic const ctl_named_node_t opt_node[] = {
225234370Sjasone	{NAME("abort"),			CTL(opt_abort)},
226234370Sjasone	{NAME("lg_chunk"),		CTL(opt_lg_chunk)},
227234370Sjasone	{NAME("narenas"),		CTL(opt_narenas)},
228234370Sjasone	{NAME("lg_dirty_mult"),		CTL(opt_lg_dirty_mult)},
229234370Sjasone	{NAME("stats_print"),		CTL(opt_stats_print)},
230234370Sjasone	{NAME("junk"),			CTL(opt_junk)},
231234370Sjasone	{NAME("zero"),			CTL(opt_zero)},
232234370Sjasone	{NAME("quarantine"),		CTL(opt_quarantine)},
233234370Sjasone	{NAME("redzone"),		CTL(opt_redzone)},
234234370Sjasone	{NAME("utrace"),		CTL(opt_utrace)},
235234370Sjasone	{NAME("valgrind"),		CTL(opt_valgrind)},
236234370Sjasone	{NAME("xmalloc"),		CTL(opt_xmalloc)},
237234370Sjasone	{NAME("tcache"),		CTL(opt_tcache)},
238234370Sjasone	{NAME("lg_tcache_max"),		CTL(opt_lg_tcache_max)},
239234370Sjasone	{NAME("prof"),			CTL(opt_prof)},
240234370Sjasone	{NAME("prof_prefix"),		CTL(opt_prof_prefix)},
241234370Sjasone	{NAME("prof_active"),		CTL(opt_prof_active)},
242234370Sjasone	{NAME("lg_prof_sample"),	CTL(opt_lg_prof_sample)},
243234370Sjasone	{NAME("lg_prof_interval"),	CTL(opt_lg_prof_interval)},
244234370Sjasone	{NAME("prof_gdump"),		CTL(opt_prof_gdump)},
245234543Sjasone	{NAME("prof_final"),		CTL(opt_prof_final)},
246234370Sjasone	{NAME("prof_leak"),		CTL(opt_prof_leak)},
247234370Sjasone	{NAME("prof_accum"),		CTL(opt_prof_accum)}
248234370Sjasone};
249234370Sjasone
250235238Sjasonestatic const ctl_named_node_t arenas_bin_i_node[] = {
251234370Sjasone	{NAME("size"),			CTL(arenas_bin_i_size)},
252234370Sjasone	{NAME("nregs"),			CTL(arenas_bin_i_nregs)},
253234370Sjasone	{NAME("run_size"),		CTL(arenas_bin_i_run_size)}
254234370Sjasone};
255235238Sjasonestatic const ctl_named_node_t super_arenas_bin_i_node[] = {
256235238Sjasone	{NAME(""),			CHILD(named, arenas_bin_i)}
257234370Sjasone};
258234370Sjasone
259235238Sjasonestatic const ctl_indexed_node_t arenas_bin_node[] = {
260234370Sjasone	{INDEX(arenas_bin_i)}
261234370Sjasone};
262234370Sjasone
263235238Sjasonestatic const ctl_named_node_t arenas_lrun_i_node[] = {
264234370Sjasone	{NAME("size"),			CTL(arenas_lrun_i_size)}
265234370Sjasone};
266235238Sjasonestatic const ctl_named_node_t super_arenas_lrun_i_node[] = {
267235238Sjasone	{NAME(""),			CHILD(named, arenas_lrun_i)}
268234370Sjasone};
269234370Sjasone
270235238Sjasonestatic const ctl_indexed_node_t arenas_lrun_node[] = {
271234370Sjasone	{INDEX(arenas_lrun_i)}
272234370Sjasone};
273234370Sjasone
274235238Sjasonestatic const ctl_named_node_t arenas_node[] = {
275234370Sjasone	{NAME("narenas"),		CTL(arenas_narenas)},
276234370Sjasone	{NAME("initialized"),		CTL(arenas_initialized)},
277234370Sjasone	{NAME("quantum"),		CTL(arenas_quantum)},
278234370Sjasone	{NAME("page"),			CTL(arenas_page)},
279234370Sjasone	{NAME("tcache_max"),		CTL(arenas_tcache_max)},
280234370Sjasone	{NAME("nbins"),			CTL(arenas_nbins)},
281234370Sjasone	{NAME("nhbins"),		CTL(arenas_nhbins)},
282235238Sjasone	{NAME("bin"),			CHILD(indexed, arenas_bin)},
283234370Sjasone	{NAME("nlruns"),		CTL(arenas_nlruns)},
284235238Sjasone	{NAME("lrun"),			CHILD(indexed, arenas_lrun)},
285234370Sjasone	{NAME("purge"),			CTL(arenas_purge)}
286234370Sjasone};
287234370Sjasone
288235238Sjasonestatic const ctl_named_node_t	prof_node[] = {
289234370Sjasone	{NAME("active"),	CTL(prof_active)},
290234370Sjasone	{NAME("dump"),		CTL(prof_dump)},
291234370Sjasone	{NAME("interval"),	CTL(prof_interval)}
292234370Sjasone};
293234370Sjasone
294235238Sjasonestatic const ctl_named_node_t stats_chunks_node[] = {
295234370Sjasone	{NAME("current"),		CTL(stats_chunks_current)},
296234370Sjasone	{NAME("total"),			CTL(stats_chunks_total)},
297234370Sjasone	{NAME("high"),			CTL(stats_chunks_high)}
298234370Sjasone};
299234370Sjasone
300235238Sjasonestatic const ctl_named_node_t stats_huge_node[] = {
301234370Sjasone	{NAME("allocated"),		CTL(stats_huge_allocated)},
302234370Sjasone	{NAME("nmalloc"),		CTL(stats_huge_nmalloc)},
303234370Sjasone	{NAME("ndalloc"),		CTL(stats_huge_ndalloc)}
304234370Sjasone};
305234370Sjasone
306235238Sjasonestatic const ctl_named_node_t stats_arenas_i_small_node[] = {
307234370Sjasone	{NAME("allocated"),		CTL(stats_arenas_i_small_allocated)},
308234370Sjasone	{NAME("nmalloc"),		CTL(stats_arenas_i_small_nmalloc)},
309234370Sjasone	{NAME("ndalloc"),		CTL(stats_arenas_i_small_ndalloc)},
310234370Sjasone	{NAME("nrequests"),		CTL(stats_arenas_i_small_nrequests)}
311234370Sjasone};
312234370Sjasone
313235238Sjasonestatic const ctl_named_node_t stats_arenas_i_large_node[] = {
314234370Sjasone	{NAME("allocated"),		CTL(stats_arenas_i_large_allocated)},
315234370Sjasone	{NAME("nmalloc"),		CTL(stats_arenas_i_large_nmalloc)},
316234370Sjasone	{NAME("ndalloc"),		CTL(stats_arenas_i_large_ndalloc)},
317234370Sjasone	{NAME("nrequests"),		CTL(stats_arenas_i_large_nrequests)}
318234370Sjasone};
319234370Sjasone
320235238Sjasonestatic const ctl_named_node_t stats_arenas_i_bins_j_node[] = {
321234370Sjasone	{NAME("allocated"),		CTL(stats_arenas_i_bins_j_allocated)},
322234370Sjasone	{NAME("nmalloc"),		CTL(stats_arenas_i_bins_j_nmalloc)},
323234370Sjasone	{NAME("ndalloc"),		CTL(stats_arenas_i_bins_j_ndalloc)},
324234370Sjasone	{NAME("nrequests"),		CTL(stats_arenas_i_bins_j_nrequests)},
325234370Sjasone	{NAME("nfills"),		CTL(stats_arenas_i_bins_j_nfills)},
326234370Sjasone	{NAME("nflushes"),		CTL(stats_arenas_i_bins_j_nflushes)},
327234370Sjasone	{NAME("nruns"),			CTL(stats_arenas_i_bins_j_nruns)},
328234370Sjasone	{NAME("nreruns"),		CTL(stats_arenas_i_bins_j_nreruns)},
329234370Sjasone	{NAME("curruns"),		CTL(stats_arenas_i_bins_j_curruns)}
330234370Sjasone};
331235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {
332235238Sjasone	{NAME(""),			CHILD(named, stats_arenas_i_bins_j)}
333234370Sjasone};
334234370Sjasone
335235238Sjasonestatic const ctl_indexed_node_t stats_arenas_i_bins_node[] = {
336234370Sjasone	{INDEX(stats_arenas_i_bins_j)}
337234370Sjasone};
338234370Sjasone
339235238Sjasonestatic const ctl_named_node_t stats_arenas_i_lruns_j_node[] = {
340234370Sjasone	{NAME("nmalloc"),		CTL(stats_arenas_i_lruns_j_nmalloc)},
341234370Sjasone	{NAME("ndalloc"),		CTL(stats_arenas_i_lruns_j_ndalloc)},
342234370Sjasone	{NAME("nrequests"),		CTL(stats_arenas_i_lruns_j_nrequests)},
343234370Sjasone	{NAME("curruns"),		CTL(stats_arenas_i_lruns_j_curruns)}
344234370Sjasone};
345235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_lruns_j_node[] = {
346235238Sjasone	{NAME(""),			CHILD(named, stats_arenas_i_lruns_j)}
347234370Sjasone};
348234370Sjasone
349235238Sjasonestatic const ctl_indexed_node_t stats_arenas_i_lruns_node[] = {
350234370Sjasone	{INDEX(stats_arenas_i_lruns_j)}
351234370Sjasone};
352234370Sjasone
353235238Sjasonestatic const ctl_named_node_t stats_arenas_i_node[] = {
354234370Sjasone	{NAME("nthreads"),		CTL(stats_arenas_i_nthreads)},
355234370Sjasone	{NAME("pactive"),		CTL(stats_arenas_i_pactive)},
356234370Sjasone	{NAME("pdirty"),		CTL(stats_arenas_i_pdirty)},
357234370Sjasone	{NAME("mapped"),		CTL(stats_arenas_i_mapped)},
358234370Sjasone	{NAME("npurge"),		CTL(stats_arenas_i_npurge)},
359234370Sjasone	{NAME("nmadvise"),		CTL(stats_arenas_i_nmadvise)},
360234370Sjasone	{NAME("purged"),		CTL(stats_arenas_i_purged)},
361235238Sjasone	{NAME("small"),			CHILD(named, stats_arenas_i_small)},
362235238Sjasone	{NAME("large"),			CHILD(named, stats_arenas_i_large)},
363235238Sjasone	{NAME("bins"),			CHILD(indexed, stats_arenas_i_bins)},
364235238Sjasone	{NAME("lruns"),			CHILD(indexed, stats_arenas_i_lruns)}
365234370Sjasone};
366235238Sjasonestatic const ctl_named_node_t super_stats_arenas_i_node[] = {
367235238Sjasone	{NAME(""),			CHILD(named, stats_arenas_i)}
368234370Sjasone};
369234370Sjasone
370235238Sjasonestatic const ctl_indexed_node_t stats_arenas_node[] = {
371234370Sjasone	{INDEX(stats_arenas_i)}
372234370Sjasone};
373234370Sjasone
374235238Sjasonestatic const ctl_named_node_t stats_node[] = {
375234370Sjasone	{NAME("cactive"),		CTL(stats_cactive)},
376234370Sjasone	{NAME("allocated"),		CTL(stats_allocated)},
377234370Sjasone	{NAME("active"),		CTL(stats_active)},
378234370Sjasone	{NAME("mapped"),		CTL(stats_mapped)},
379235238Sjasone	{NAME("chunks"),		CHILD(named, stats_chunks)},
380235238Sjasone	{NAME("huge"),			CHILD(named, stats_huge)},
381235238Sjasone	{NAME("arenas"),		CHILD(indexed, stats_arenas)}
382234370Sjasone};
383234370Sjasone
384235238Sjasonestatic const ctl_named_node_t	root_node[] = {
385234370Sjasone	{NAME("version"),	CTL(version)},
386234370Sjasone	{NAME("epoch"),		CTL(epoch)},
387235238Sjasone	{NAME("thread"),	CHILD(named, thread)},
388235238Sjasone	{NAME("config"),	CHILD(named, config)},
389235238Sjasone	{NAME("opt"),		CHILD(named, opt)},
390235238Sjasone	{NAME("arenas"),	CHILD(named, arenas)},
391235238Sjasone	{NAME("prof"),		CHILD(named, prof)},
392235238Sjasone	{NAME("stats"),		CHILD(named, stats)}
393234370Sjasone};
394235238Sjasonestatic const ctl_named_node_t super_root_node[] = {
395235238Sjasone	{NAME(""),		CHILD(named, root)}
396234370Sjasone};
397234370Sjasone
398234370Sjasone#undef NAME
399234370Sjasone#undef CHILD
400234370Sjasone#undef CTL
401234370Sjasone#undef INDEX
402234370Sjasone
403234370Sjasone/******************************************************************************/
404234370Sjasone
405234370Sjasonestatic bool
406234370Sjasonectl_arena_init(ctl_arena_stats_t *astats)
407234370Sjasone{
408234370Sjasone
409234370Sjasone	if (astats->lstats == NULL) {
410234370Sjasone		astats->lstats = (malloc_large_stats_t *)base_alloc(nlclasses *
411234370Sjasone		    sizeof(malloc_large_stats_t));
412234370Sjasone		if (astats->lstats == NULL)
413234370Sjasone			return (true);
414234370Sjasone	}
415234370Sjasone
416234370Sjasone	return (false);
417234370Sjasone}
418234370Sjasone
419234370Sjasonestatic void
420234370Sjasonectl_arena_clear(ctl_arena_stats_t *astats)
421234370Sjasone{
422234370Sjasone
423234370Sjasone	astats->pactive = 0;
424234370Sjasone	astats->pdirty = 0;
425234370Sjasone	if (config_stats) {
426234370Sjasone		memset(&astats->astats, 0, sizeof(arena_stats_t));
427234370Sjasone		astats->allocated_small = 0;
428234370Sjasone		astats->nmalloc_small = 0;
429234370Sjasone		astats->ndalloc_small = 0;
430234370Sjasone		astats->nrequests_small = 0;
431234370Sjasone		memset(astats->bstats, 0, NBINS * sizeof(malloc_bin_stats_t));
432234370Sjasone		memset(astats->lstats, 0, nlclasses *
433234370Sjasone		    sizeof(malloc_large_stats_t));
434234370Sjasone	}
435234370Sjasone}
436234370Sjasone
437234370Sjasonestatic void
438234370Sjasonectl_arena_stats_amerge(ctl_arena_stats_t *cstats, arena_t *arena)
439234370Sjasone{
440234370Sjasone	unsigned i;
441234370Sjasone
442234370Sjasone	arena_stats_merge(arena, &cstats->pactive, &cstats->pdirty,
443234370Sjasone	    &cstats->astats, cstats->bstats, cstats->lstats);
444234370Sjasone
445234370Sjasone	for (i = 0; i < NBINS; i++) {
446234370Sjasone		cstats->allocated_small += cstats->bstats[i].allocated;
447234370Sjasone		cstats->nmalloc_small += cstats->bstats[i].nmalloc;
448234370Sjasone		cstats->ndalloc_small += cstats->bstats[i].ndalloc;
449234370Sjasone		cstats->nrequests_small += cstats->bstats[i].nrequests;
450234370Sjasone	}
451234370Sjasone}
452234370Sjasone
453234370Sjasonestatic void
454234370Sjasonectl_arena_stats_smerge(ctl_arena_stats_t *sstats, ctl_arena_stats_t *astats)
455234370Sjasone{
456234370Sjasone	unsigned i;
457234370Sjasone
458234370Sjasone	sstats->pactive += astats->pactive;
459234370Sjasone	sstats->pdirty += astats->pdirty;
460234370Sjasone
461234370Sjasone	sstats->astats.mapped += astats->astats.mapped;
462234370Sjasone	sstats->astats.npurge += astats->astats.npurge;
463234370Sjasone	sstats->astats.nmadvise += astats->astats.nmadvise;
464234370Sjasone	sstats->astats.purged += astats->astats.purged;
465234370Sjasone
466234370Sjasone	sstats->allocated_small += astats->allocated_small;
467234370Sjasone	sstats->nmalloc_small += astats->nmalloc_small;
468234370Sjasone	sstats->ndalloc_small += astats->ndalloc_small;
469234370Sjasone	sstats->nrequests_small += astats->nrequests_small;
470234370Sjasone
471234370Sjasone	sstats->astats.allocated_large += astats->astats.allocated_large;
472234370Sjasone	sstats->astats.nmalloc_large += astats->astats.nmalloc_large;
473234370Sjasone	sstats->astats.ndalloc_large += astats->astats.ndalloc_large;
474234370Sjasone	sstats->astats.nrequests_large += astats->astats.nrequests_large;
475234370Sjasone
476234370Sjasone	for (i = 0; i < nlclasses; i++) {
477234370Sjasone		sstats->lstats[i].nmalloc += astats->lstats[i].nmalloc;
478234370Sjasone		sstats->lstats[i].ndalloc += astats->lstats[i].ndalloc;
479234370Sjasone		sstats->lstats[i].nrequests += astats->lstats[i].nrequests;
480234370Sjasone		sstats->lstats[i].curruns += astats->lstats[i].curruns;
481234370Sjasone	}
482234370Sjasone
483234370Sjasone	for (i = 0; i < NBINS; i++) {
484234370Sjasone		sstats->bstats[i].allocated += astats->bstats[i].allocated;
485234370Sjasone		sstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
486234370Sjasone		sstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
487234370Sjasone		sstats->bstats[i].nrequests += astats->bstats[i].nrequests;
488234370Sjasone		if (config_tcache) {
489234370Sjasone			sstats->bstats[i].nfills += astats->bstats[i].nfills;
490234370Sjasone			sstats->bstats[i].nflushes +=
491234370Sjasone			    astats->bstats[i].nflushes;
492234370Sjasone		}
493234370Sjasone		sstats->bstats[i].nruns += astats->bstats[i].nruns;
494234370Sjasone		sstats->bstats[i].reruns += astats->bstats[i].reruns;
495234370Sjasone		sstats->bstats[i].curruns += astats->bstats[i].curruns;
496234370Sjasone	}
497234370Sjasone}
498234370Sjasone
499234370Sjasonestatic void
500234370Sjasonectl_arena_refresh(arena_t *arena, unsigned i)
501234370Sjasone{
502234370Sjasone	ctl_arena_stats_t *astats = &ctl_stats.arenas[i];
503234370Sjasone	ctl_arena_stats_t *sstats = &ctl_stats.arenas[narenas];
504234370Sjasone
505234370Sjasone	ctl_arena_clear(astats);
506234370Sjasone
507234370Sjasone	sstats->nthreads += astats->nthreads;
508234370Sjasone	if (config_stats) {
509234370Sjasone		ctl_arena_stats_amerge(astats, arena);
510234370Sjasone		/* Merge into sum stats as well. */
511234370Sjasone		ctl_arena_stats_smerge(sstats, astats);
512234370Sjasone	} else {
513234370Sjasone		astats->pactive += arena->nactive;
514234370Sjasone		astats->pdirty += arena->ndirty;
515234370Sjasone		/* Merge into sum stats as well. */
516234370Sjasone		sstats->pactive += arena->nactive;
517234370Sjasone		sstats->pdirty += arena->ndirty;
518234370Sjasone	}
519234370Sjasone}
520234370Sjasone
521234370Sjasonestatic void
522234370Sjasonectl_refresh(void)
523234370Sjasone{
524234370Sjasone	unsigned i;
525235238Sjasone	VARIABLE_ARRAY(arena_t *, tarenas, narenas);
526234370Sjasone
527234370Sjasone	if (config_stats) {
528234370Sjasone		malloc_mutex_lock(&chunks_mtx);
529234370Sjasone		ctl_stats.chunks.current = stats_chunks.curchunks;
530234370Sjasone		ctl_stats.chunks.total = stats_chunks.nchunks;
531234370Sjasone		ctl_stats.chunks.high = stats_chunks.highchunks;
532234370Sjasone		malloc_mutex_unlock(&chunks_mtx);
533234370Sjasone
534234370Sjasone		malloc_mutex_lock(&huge_mtx);
535234370Sjasone		ctl_stats.huge.allocated = huge_allocated;
536234370Sjasone		ctl_stats.huge.nmalloc = huge_nmalloc;
537234370Sjasone		ctl_stats.huge.ndalloc = huge_ndalloc;
538234370Sjasone		malloc_mutex_unlock(&huge_mtx);
539234370Sjasone	}
540234370Sjasone
541234370Sjasone	/*
542234370Sjasone	 * Clear sum stats, since they will be merged into by
543234370Sjasone	 * ctl_arena_refresh().
544234370Sjasone	 */
545234370Sjasone	ctl_stats.arenas[narenas].nthreads = 0;
546234370Sjasone	ctl_arena_clear(&ctl_stats.arenas[narenas]);
547234370Sjasone
548234370Sjasone	malloc_mutex_lock(&arenas_lock);
549234370Sjasone	memcpy(tarenas, arenas, sizeof(arena_t *) * narenas);
550234370Sjasone	for (i = 0; i < narenas; i++) {
551234370Sjasone		if (arenas[i] != NULL)
552234370Sjasone			ctl_stats.arenas[i].nthreads = arenas[i]->nthreads;
553234370Sjasone		else
554234370Sjasone			ctl_stats.arenas[i].nthreads = 0;
555234370Sjasone	}
556234370Sjasone	malloc_mutex_unlock(&arenas_lock);
557234370Sjasone	for (i = 0; i < narenas; i++) {
558234370Sjasone		bool initialized = (tarenas[i] != NULL);
559234370Sjasone
560234370Sjasone		ctl_stats.arenas[i].initialized = initialized;
561234370Sjasone		if (initialized)
562234370Sjasone			ctl_arena_refresh(tarenas[i], i);
563234370Sjasone	}
564234370Sjasone
565234370Sjasone	if (config_stats) {
566234370Sjasone		ctl_stats.allocated = ctl_stats.arenas[narenas].allocated_small
567234370Sjasone		    + ctl_stats.arenas[narenas].astats.allocated_large
568234370Sjasone		    + ctl_stats.huge.allocated;
569234370Sjasone		ctl_stats.active = (ctl_stats.arenas[narenas].pactive <<
570234370Sjasone		    LG_PAGE) + ctl_stats.huge.allocated;
571234370Sjasone		ctl_stats.mapped = (ctl_stats.chunks.current << opt_lg_chunk);
572234370Sjasone	}
573234370Sjasone
574234370Sjasone	ctl_epoch++;
575234370Sjasone}
576234370Sjasone
577234370Sjasonestatic bool
578234370Sjasonectl_init(void)
579234370Sjasone{
580234370Sjasone	bool ret;
581234370Sjasone
582234370Sjasone	malloc_mutex_lock(&ctl_mtx);
583234370Sjasone	if (ctl_initialized == false) {
584234370Sjasone		/*
585234370Sjasone		 * Allocate space for one extra arena stats element, which
586234370Sjasone		 * contains summed stats across all arenas.
587234370Sjasone		 */
588234370Sjasone		ctl_stats.arenas = (ctl_arena_stats_t *)base_alloc(
589234370Sjasone		    (narenas + 1) * sizeof(ctl_arena_stats_t));
590234370Sjasone		if (ctl_stats.arenas == NULL) {
591234370Sjasone			ret = true;
592234370Sjasone			goto label_return;
593234370Sjasone		}
594234370Sjasone		memset(ctl_stats.arenas, 0, (narenas + 1) *
595234370Sjasone		    sizeof(ctl_arena_stats_t));
596234370Sjasone
597234370Sjasone		/*
598234370Sjasone		 * Initialize all stats structures, regardless of whether they
599234370Sjasone		 * ever get used.  Lazy initialization would allow errors to
600234370Sjasone		 * cause inconsistent state to be viewable by the application.
601234370Sjasone		 */
602234370Sjasone		if (config_stats) {
603234370Sjasone			unsigned i;
604234370Sjasone			for (i = 0; i <= narenas; i++) {
605234370Sjasone				if (ctl_arena_init(&ctl_stats.arenas[i])) {
606234370Sjasone					ret = true;
607234370Sjasone					goto label_return;
608234370Sjasone				}
609234370Sjasone			}
610234370Sjasone		}
611234370Sjasone		ctl_stats.arenas[narenas].initialized = true;
612234370Sjasone
613234370Sjasone		ctl_epoch = 0;
614234370Sjasone		ctl_refresh();
615234370Sjasone		ctl_initialized = true;
616234370Sjasone	}
617234370Sjasone
618234370Sjasone	ret = false;
619234370Sjasonelabel_return:
620234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
621234370Sjasone	return (ret);
622234370Sjasone}
623234370Sjasone
624234370Sjasonestatic int
625234370Sjasonectl_lookup(const char *name, ctl_node_t const **nodesp, size_t *mibp,
626234370Sjasone    size_t *depthp)
627234370Sjasone{
628234370Sjasone	int ret;
629234370Sjasone	const char *elm, *tdot, *dot;
630234370Sjasone	size_t elen, i, j;
631235238Sjasone	const ctl_named_node_t *node;
632234370Sjasone
633234370Sjasone	elm = name;
634234370Sjasone	/* Equivalent to strchrnul(). */
635234370Sjasone	dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
636234370Sjasone	elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
637234370Sjasone	if (elen == 0) {
638234370Sjasone		ret = ENOENT;
639234370Sjasone		goto label_return;
640234370Sjasone	}
641234370Sjasone	node = super_root_node;
642234370Sjasone	for (i = 0; i < *depthp; i++) {
643235238Sjasone		assert(node);
644235238Sjasone		assert(node->nchildren > 0);
645235238Sjasone		if (ctl_named_node(node->children) != NULL) {
646235238Sjasone			const ctl_named_node_t *pnode = node;
647234370Sjasone
648234370Sjasone			/* Children are named. */
649235238Sjasone			for (j = 0; j < node->nchildren; j++) {
650235238Sjasone				const ctl_named_node_t *child =
651235238Sjasone				    ctl_named_children(node, j);
652235238Sjasone				if (strlen(child->name) == elen &&
653235238Sjasone				    strncmp(elm, child->name, elen) == 0) {
654234370Sjasone					node = child;
655234370Sjasone					if (nodesp != NULL)
656235238Sjasone						nodesp[i] =
657235238Sjasone						    (const ctl_node_t *)node;
658234370Sjasone					mibp[i] = j;
659234370Sjasone					break;
660234370Sjasone				}
661234370Sjasone			}
662234370Sjasone			if (node == pnode) {
663234370Sjasone				ret = ENOENT;
664234370Sjasone				goto label_return;
665234370Sjasone			}
666234370Sjasone		} else {
667234370Sjasone			uintmax_t index;
668235238Sjasone			const ctl_indexed_node_t *inode;
669234370Sjasone
670234370Sjasone			/* Children are indexed. */
671234370Sjasone			index = malloc_strtoumax(elm, NULL, 10);
672234370Sjasone			if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
673234370Sjasone				ret = ENOENT;
674234370Sjasone				goto label_return;
675234370Sjasone			}
676234370Sjasone
677235238Sjasone			inode = ctl_indexed_node(node->children);
678235238Sjasone			node = inode->index(mibp, *depthp, (size_t)index);
679234370Sjasone			if (node == NULL) {
680234370Sjasone				ret = ENOENT;
681234370Sjasone				goto label_return;
682234370Sjasone			}
683234370Sjasone
684234370Sjasone			if (nodesp != NULL)
685235238Sjasone				nodesp[i] = (const ctl_node_t *)node;
686234370Sjasone			mibp[i] = (size_t)index;
687234370Sjasone		}
688234370Sjasone
689234370Sjasone		if (node->ctl != NULL) {
690234370Sjasone			/* Terminal node. */
691234370Sjasone			if (*dot != '\0') {
692234370Sjasone				/*
693234370Sjasone				 * The name contains more elements than are
694234370Sjasone				 * in this path through the tree.
695234370Sjasone				 */
696234370Sjasone				ret = ENOENT;
697234370Sjasone				goto label_return;
698234370Sjasone			}
699234370Sjasone			/* Complete lookup successful. */
700234370Sjasone			*depthp = i + 1;
701234370Sjasone			break;
702234370Sjasone		}
703234370Sjasone
704234370Sjasone		/* Update elm. */
705234370Sjasone		if (*dot == '\0') {
706234370Sjasone			/* No more elements. */
707234370Sjasone			ret = ENOENT;
708234370Sjasone			goto label_return;
709234370Sjasone		}
710234370Sjasone		elm = &dot[1];
711234370Sjasone		dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
712234370Sjasone		    strchr(elm, '\0');
713234370Sjasone		elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
714234370Sjasone	}
715234370Sjasone
716234370Sjasone	ret = 0;
717234370Sjasonelabel_return:
718234370Sjasone	return (ret);
719234370Sjasone}
720234370Sjasone
721234370Sjasoneint
722234370Sjasonectl_byname(const char *name, void *oldp, size_t *oldlenp, void *newp,
723234370Sjasone    size_t newlen)
724234370Sjasone{
725234370Sjasone	int ret;
726234370Sjasone	size_t depth;
727234370Sjasone	ctl_node_t const *nodes[CTL_MAX_DEPTH];
728234370Sjasone	size_t mib[CTL_MAX_DEPTH];
729235238Sjasone	const ctl_named_node_t *node;
730234370Sjasone
731234370Sjasone	if (ctl_initialized == false && ctl_init()) {
732234370Sjasone		ret = EAGAIN;
733234370Sjasone		goto label_return;
734234370Sjasone	}
735234370Sjasone
736234370Sjasone	depth = CTL_MAX_DEPTH;
737234370Sjasone	ret = ctl_lookup(name, nodes, mib, &depth);
738234370Sjasone	if (ret != 0)
739234370Sjasone		goto label_return;
740234370Sjasone
741235238Sjasone	node = ctl_named_node(nodes[depth-1]);
742235238Sjasone	if (node != NULL && node->ctl)
743235238Sjasone		ret = node->ctl(mib, depth, oldp, oldlenp, newp, newlen);
744235238Sjasone	else {
745234370Sjasone		/* The name refers to a partial path through the ctl tree. */
746234370Sjasone		ret = ENOENT;
747234370Sjasone	}
748234370Sjasone
749234370Sjasonelabel_return:
750234370Sjasone	return(ret);
751234370Sjasone}
752234370Sjasone
753234370Sjasoneint
754234370Sjasonectl_nametomib(const char *name, size_t *mibp, size_t *miblenp)
755234370Sjasone{
756234370Sjasone	int ret;
757234370Sjasone
758234370Sjasone	if (ctl_initialized == false && ctl_init()) {
759234370Sjasone		ret = EAGAIN;
760234370Sjasone		goto label_return;
761234370Sjasone	}
762234370Sjasone
763234370Sjasone	ret = ctl_lookup(name, NULL, mibp, miblenp);
764234370Sjasonelabel_return:
765234370Sjasone	return(ret);
766234370Sjasone}
767234370Sjasone
768234370Sjasoneint
769234370Sjasonectl_bymib(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
770234370Sjasone    void *newp, size_t newlen)
771234370Sjasone{
772234370Sjasone	int ret;
773235238Sjasone	const ctl_named_node_t *node;
774234370Sjasone	size_t i;
775234370Sjasone
776234370Sjasone	if (ctl_initialized == false && ctl_init()) {
777234370Sjasone		ret = EAGAIN;
778234370Sjasone		goto label_return;
779234370Sjasone	}
780234370Sjasone
781234370Sjasone	/* Iterate down the tree. */
782234370Sjasone	node = super_root_node;
783234370Sjasone	for (i = 0; i < miblen; i++) {
784235238Sjasone		assert(node);
785235238Sjasone		assert(node->nchildren > 0);
786235238Sjasone		if (ctl_named_node(node->children) != NULL) {
787234370Sjasone			/* Children are named. */
788235238Sjasone			if (node->nchildren <= mib[i]) {
789234370Sjasone				ret = ENOENT;
790234370Sjasone				goto label_return;
791234370Sjasone			}
792235238Sjasone			node = ctl_named_children(node, mib[i]);
793234370Sjasone		} else {
794235238Sjasone			const ctl_indexed_node_t *inode;
795234370Sjasone
796234370Sjasone			/* Indexed element. */
797235238Sjasone			inode = ctl_indexed_node(node->children);
798235238Sjasone			node = inode->index(mib, miblen, mib[i]);
799234370Sjasone			if (node == NULL) {
800234370Sjasone				ret = ENOENT;
801234370Sjasone				goto label_return;
802234370Sjasone			}
803234370Sjasone		}
804234370Sjasone	}
805234370Sjasone
806234370Sjasone	/* Call the ctl function. */
807235238Sjasone	if (node && node->ctl)
808235238Sjasone		ret = node->ctl(mib, miblen, oldp, oldlenp, newp, newlen);
809235238Sjasone	else {
810234370Sjasone		/* Partial MIB. */
811234370Sjasone		ret = ENOENT;
812234370Sjasone	}
813234370Sjasone
814234370Sjasonelabel_return:
815234370Sjasone	return(ret);
816234370Sjasone}
817234370Sjasone
818234370Sjasonebool
819234370Sjasonectl_boot(void)
820234370Sjasone{
821234370Sjasone
822234370Sjasone	if (malloc_mutex_init(&ctl_mtx))
823234370Sjasone		return (true);
824234370Sjasone
825234370Sjasone	ctl_initialized = false;
826234370Sjasone
827234370Sjasone	return (false);
828234370Sjasone}
829234370Sjasone
830234370Sjasone/******************************************************************************/
831234370Sjasone/* *_ctl() functions. */
832234370Sjasone
833234370Sjasone#define	READONLY()	do {						\
834234370Sjasone	if (newp != NULL || newlen != 0) {				\
835234370Sjasone		ret = EPERM;						\
836235238Sjasone		goto label_return;					\
837234370Sjasone	}								\
838234370Sjasone} while (0)
839234370Sjasone
840234370Sjasone#define	WRITEONLY()	do {						\
841234370Sjasone	if (oldp != NULL || oldlenp != NULL) {				\
842234370Sjasone		ret = EPERM;						\
843235238Sjasone		goto label_return;					\
844234370Sjasone	}								\
845234370Sjasone} while (0)
846234370Sjasone
847234370Sjasone#define	READ(v, t)	do {						\
848234370Sjasone	if (oldp != NULL && oldlenp != NULL) {				\
849234370Sjasone		if (*oldlenp != sizeof(t)) {				\
850234370Sjasone			size_t	copylen = (sizeof(t) <= *oldlenp)	\
851234370Sjasone			    ? sizeof(t) : *oldlenp;			\
852234370Sjasone			memcpy(oldp, (void *)&v, copylen);		\
853234370Sjasone			ret = EINVAL;					\
854235238Sjasone			goto label_return;				\
855234370Sjasone		} else							\
856234370Sjasone			*(t *)oldp = v;					\
857234370Sjasone	}								\
858234370Sjasone} while (0)
859234370Sjasone
860234370Sjasone#define	WRITE(v, t)	do {						\
861234370Sjasone	if (newp != NULL) {						\
862234370Sjasone		if (newlen != sizeof(t)) {				\
863234370Sjasone			ret = EINVAL;					\
864235238Sjasone			goto label_return;				\
865234370Sjasone		}							\
866234370Sjasone		v = *(t *)newp;						\
867234370Sjasone	}								\
868234370Sjasone} while (0)
869234370Sjasone
870234370Sjasone/*
871234370Sjasone * There's a lot of code duplication in the following macros due to limitations
872234370Sjasone * in how nested cpp macros are expanded.
873234370Sjasone */
874234370Sjasone#define	CTL_RO_CLGEN(c, l, n, v, t)					\
875234370Sjasonestatic int								\
876234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
877234370Sjasone    void *newp, size_t newlen)						\
878234370Sjasone{									\
879234370Sjasone	int ret;							\
880234370Sjasone	t oldval;							\
881234370Sjasone									\
882234370Sjasone	if ((c) == false)						\
883234370Sjasone		return (ENOENT);					\
884234370Sjasone	if (l)								\
885234370Sjasone		malloc_mutex_lock(&ctl_mtx);				\
886234370Sjasone	READONLY();							\
887234370Sjasone	oldval = v;							\
888234370Sjasone	READ(oldval, t);						\
889234370Sjasone									\
890234370Sjasone	ret = 0;							\
891235238Sjasonelabel_return:								\
892234370Sjasone	if (l)								\
893234370Sjasone		malloc_mutex_unlock(&ctl_mtx);				\
894234370Sjasone	return (ret);							\
895234370Sjasone}
896234370Sjasone
897234370Sjasone#define	CTL_RO_CGEN(c, n, v, t)						\
898234370Sjasonestatic int								\
899234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
900234370Sjasone    void *newp, size_t newlen)						\
901234370Sjasone{									\
902234370Sjasone	int ret;							\
903234370Sjasone	t oldval;							\
904234370Sjasone									\
905234370Sjasone	if ((c) == false)						\
906234370Sjasone		return (ENOENT);					\
907234370Sjasone	malloc_mutex_lock(&ctl_mtx);					\
908234370Sjasone	READONLY();							\
909234370Sjasone	oldval = v;							\
910234370Sjasone	READ(oldval, t);						\
911234370Sjasone									\
912234370Sjasone	ret = 0;							\
913235238Sjasonelabel_return:								\
914234370Sjasone	malloc_mutex_unlock(&ctl_mtx);					\
915234370Sjasone	return (ret);							\
916234370Sjasone}
917234370Sjasone
918234370Sjasone#define	CTL_RO_GEN(n, v, t)						\
919234370Sjasonestatic int								\
920234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
921234370Sjasone    void *newp, size_t newlen)						\
922234370Sjasone{									\
923234370Sjasone	int ret;							\
924234370Sjasone	t oldval;							\
925234370Sjasone									\
926234370Sjasone	malloc_mutex_lock(&ctl_mtx);					\
927234370Sjasone	READONLY();							\
928234370Sjasone	oldval = v;							\
929234370Sjasone	READ(oldval, t);						\
930234370Sjasone									\
931234370Sjasone	ret = 0;							\
932235238Sjasonelabel_return:								\
933234370Sjasone	malloc_mutex_unlock(&ctl_mtx);					\
934234370Sjasone	return (ret);							\
935234370Sjasone}
936234370Sjasone
937234370Sjasone/*
938234370Sjasone * ctl_mtx is not acquired, under the assumption that no pertinent data will
939234370Sjasone * mutate during the call.
940234370Sjasone */
941234370Sjasone#define	CTL_RO_NL_CGEN(c, n, v, t)					\
942234370Sjasonestatic int								\
943234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
944234370Sjasone    void *newp, size_t newlen)						\
945234370Sjasone{									\
946234370Sjasone	int ret;							\
947234370Sjasone	t oldval;							\
948234370Sjasone									\
949234370Sjasone	if ((c) == false)						\
950234370Sjasone		return (ENOENT);					\
951234370Sjasone	READONLY();							\
952234370Sjasone	oldval = v;							\
953234370Sjasone	READ(oldval, t);						\
954234370Sjasone									\
955234370Sjasone	ret = 0;							\
956235238Sjasonelabel_return:								\
957234370Sjasone	return (ret);							\
958234370Sjasone}
959234370Sjasone
960234370Sjasone#define	CTL_RO_NL_GEN(n, v, t)						\
961234370Sjasonestatic int								\
962234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
963234370Sjasone    void *newp, size_t newlen)						\
964234370Sjasone{									\
965234370Sjasone	int ret;							\
966234370Sjasone	t oldval;							\
967234370Sjasone									\
968234370Sjasone	READONLY();							\
969234370Sjasone	oldval = v;							\
970234370Sjasone	READ(oldval, t);						\
971234370Sjasone									\
972234370Sjasone	ret = 0;							\
973235238Sjasonelabel_return:								\
974234370Sjasone	return (ret);							\
975234370Sjasone}
976234370Sjasone
977234370Sjasone#define	CTL_RO_BOOL_CONFIG_GEN(n)					\
978234370Sjasonestatic int								\
979234370Sjasonen##_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,	\
980234370Sjasone    void *newp, size_t newlen)						\
981234370Sjasone{									\
982234370Sjasone	int ret;							\
983234370Sjasone	bool oldval;							\
984234370Sjasone									\
985234370Sjasone	READONLY();							\
986234370Sjasone	oldval = n;							\
987234370Sjasone	READ(oldval, bool);						\
988234370Sjasone									\
989234370Sjasone	ret = 0;							\
990235238Sjasonelabel_return:								\
991234370Sjasone	return (ret);							\
992234370Sjasone}
993234370Sjasone
994234370SjasoneCTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
995234370Sjasone
996234370Sjasonestatic int
997234370Sjasoneepoch_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
998234370Sjasone    void *newp, size_t newlen)
999234370Sjasone{
1000234370Sjasone	int ret;
1001234370Sjasone	uint64_t newval;
1002234370Sjasone
1003234370Sjasone	malloc_mutex_lock(&ctl_mtx);
1004234370Sjasone	WRITE(newval, uint64_t);
1005235238Sjasone	if (newp != NULL)
1006234370Sjasone		ctl_refresh();
1007234370Sjasone	READ(ctl_epoch, uint64_t);
1008234370Sjasone
1009234370Sjasone	ret = 0;
1010234370Sjasonelabel_return:
1011234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
1012234370Sjasone	return (ret);
1013234370Sjasone}
1014234370Sjasone
1015234370Sjasonestatic int
1016234370Sjasonethread_tcache_enabled_ctl(const size_t *mib, size_t miblen, void *oldp,
1017234370Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1018234370Sjasone{
1019234370Sjasone	int ret;
1020234370Sjasone	bool oldval;
1021234370Sjasone
1022234370Sjasone	if (config_tcache == false)
1023234370Sjasone		return (ENOENT);
1024234370Sjasone
1025234370Sjasone	oldval = tcache_enabled_get();
1026234370Sjasone	if (newp != NULL) {
1027234370Sjasone		if (newlen != sizeof(bool)) {
1028234370Sjasone			ret = EINVAL;
1029234370Sjasone			goto label_return;
1030234370Sjasone		}
1031234370Sjasone		tcache_enabled_set(*(bool *)newp);
1032234370Sjasone	}
1033234370Sjasone	READ(oldval, bool);
1034234370Sjasone
1035234370Sjasonelabel_return:
1036234370Sjasone	ret = 0;
1037234370Sjasone	return (ret);
1038234370Sjasone}
1039234370Sjasone
1040234370Sjasonestatic int
1041234370Sjasonethread_tcache_flush_ctl(const size_t *mib, size_t miblen, void *oldp,
1042234370Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1043234370Sjasone{
1044234370Sjasone	int ret;
1045234370Sjasone
1046234370Sjasone	if (config_tcache == false)
1047234370Sjasone		return (ENOENT);
1048234370Sjasone
1049235238Sjasone	READONLY();
1050235238Sjasone	WRITEONLY();
1051234370Sjasone
1052234370Sjasone	tcache_flush();
1053234370Sjasone
1054234370Sjasone	ret = 0;
1055234370Sjasonelabel_return:
1056234370Sjasone	return (ret);
1057234370Sjasone}
1058234370Sjasone
1059234370Sjasonestatic int
1060234370Sjasonethread_arena_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1061234370Sjasone    void *newp, size_t newlen)
1062234370Sjasone{
1063234370Sjasone	int ret;
1064234370Sjasone	unsigned newind, oldind;
1065234370Sjasone
1066234370Sjasone	newind = oldind = choose_arena(NULL)->ind;
1067234370Sjasone	WRITE(newind, unsigned);
1068234370Sjasone	READ(oldind, unsigned);
1069234370Sjasone	if (newind != oldind) {
1070234370Sjasone		arena_t *arena;
1071234370Sjasone
1072234370Sjasone		if (newind >= narenas) {
1073234370Sjasone			/* New arena index is out of range. */
1074234370Sjasone			ret = EFAULT;
1075234370Sjasone			goto label_return;
1076234370Sjasone		}
1077234370Sjasone
1078234370Sjasone		/* Initialize arena if necessary. */
1079234370Sjasone		malloc_mutex_lock(&arenas_lock);
1080234370Sjasone		if ((arena = arenas[newind]) == NULL && (arena =
1081234370Sjasone		    arenas_extend(newind)) == NULL) {
1082234370Sjasone			malloc_mutex_unlock(&arenas_lock);
1083234370Sjasone			ret = EAGAIN;
1084234370Sjasone			goto label_return;
1085234370Sjasone		}
1086234370Sjasone		assert(arena == arenas[newind]);
1087234370Sjasone		arenas[oldind]->nthreads--;
1088234370Sjasone		arenas[newind]->nthreads++;
1089234370Sjasone		malloc_mutex_unlock(&arenas_lock);
1090234370Sjasone
1091234370Sjasone		/* Set new arena association. */
1092234370Sjasone		if (config_tcache) {
1093234370Sjasone			tcache_t *tcache;
1094234370Sjasone			if ((uintptr_t)(tcache = *tcache_tsd_get()) >
1095234370Sjasone			    (uintptr_t)TCACHE_STATE_MAX) {
1096234370Sjasone				tcache_arena_dissociate(tcache);
1097234370Sjasone				tcache_arena_associate(tcache, arena);
1098234370Sjasone			}
1099234370Sjasone		}
1100234370Sjasone		arenas_tsd_set(&arena);
1101234370Sjasone	}
1102234370Sjasone
1103234370Sjasone	ret = 0;
1104234370Sjasonelabel_return:
1105234370Sjasone	return (ret);
1106234370Sjasone}
1107234370Sjasone
1108234370SjasoneCTL_RO_NL_CGEN(config_stats, thread_allocated,
1109234370Sjasone    thread_allocated_tsd_get()->allocated, uint64_t)
1110234370SjasoneCTL_RO_NL_CGEN(config_stats, thread_allocatedp,
1111234370Sjasone    &thread_allocated_tsd_get()->allocated, uint64_t *)
1112234370SjasoneCTL_RO_NL_CGEN(config_stats, thread_deallocated,
1113234370Sjasone    thread_allocated_tsd_get()->deallocated, uint64_t)
1114234370SjasoneCTL_RO_NL_CGEN(config_stats, thread_deallocatedp,
1115234370Sjasone    &thread_allocated_tsd_get()->deallocated, uint64_t *)
1116234370Sjasone
1117234370Sjasone/******************************************************************************/
1118234370Sjasone
1119234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_debug)
1120234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_dss)
1121234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_fill)
1122234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_lazy_lock)
1123235238SjasoneCTL_RO_BOOL_CONFIG_GEN(config_mremap)
1124234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_munmap)
1125234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_prof)
1126234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_prof_libgcc)
1127234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_prof_libunwind)
1128234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_stats)
1129234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_tcache)
1130234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_tls)
1131234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_utrace)
1132234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_valgrind)
1133234370SjasoneCTL_RO_BOOL_CONFIG_GEN(config_xmalloc)
1134234370Sjasone
1135234370Sjasone/******************************************************************************/
1136234370Sjasone
1137234370SjasoneCTL_RO_NL_GEN(opt_abort, opt_abort, bool)
1138234370SjasoneCTL_RO_NL_GEN(opt_lg_chunk, opt_lg_chunk, size_t)
1139234370SjasoneCTL_RO_NL_GEN(opt_narenas, opt_narenas, size_t)
1140234370SjasoneCTL_RO_NL_GEN(opt_lg_dirty_mult, opt_lg_dirty_mult, ssize_t)
1141234370SjasoneCTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
1142234370SjasoneCTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, bool)
1143234370SjasoneCTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
1144234370SjasoneCTL_RO_NL_CGEN(config_fill, opt_quarantine, opt_quarantine, size_t)
1145234370SjasoneCTL_RO_NL_CGEN(config_fill, opt_redzone, opt_redzone, bool)
1146234370SjasoneCTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
1147234370SjasoneCTL_RO_NL_CGEN(config_valgrind, opt_valgrind, opt_valgrind, bool)
1148234370SjasoneCTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
1149234370SjasoneCTL_RO_NL_CGEN(config_tcache, opt_tcache, opt_tcache, bool)
1150234370SjasoneCTL_RO_NL_CGEN(config_tcache, opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
1151234370SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
1152234370SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
1153234370SjasoneCTL_RO_CGEN(config_prof, opt_prof_active, opt_prof_active, bool) /* Mutable. */
1154234370SjasoneCTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
1155234370SjasoneCTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
1156234370SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
1157234543SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
1158234370SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
1159234370SjasoneCTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
1160234370Sjasone
1161234370Sjasone/******************************************************************************/
1162234370Sjasone
1163234370SjasoneCTL_RO_NL_GEN(arenas_bin_i_size, arena_bin_info[mib[2]].reg_size, size_t)
1164234370SjasoneCTL_RO_NL_GEN(arenas_bin_i_nregs, arena_bin_info[mib[2]].nregs, uint32_t)
1165234370SjasoneCTL_RO_NL_GEN(arenas_bin_i_run_size, arena_bin_info[mib[2]].run_size, size_t)
1166235238Sjasoneconst ctl_named_node_t *
1167234370Sjasonearenas_bin_i_index(const size_t *mib, size_t miblen, size_t i)
1168234370Sjasone{
1169234370Sjasone
1170234370Sjasone	if (i > NBINS)
1171234370Sjasone		return (NULL);
1172234370Sjasone	return (super_arenas_bin_i_node);
1173234370Sjasone}
1174234370Sjasone
1175234370SjasoneCTL_RO_NL_GEN(arenas_lrun_i_size, ((mib[2]+1) << LG_PAGE), size_t)
1176235238Sjasoneconst ctl_named_node_t *
1177234370Sjasonearenas_lrun_i_index(const size_t *mib, size_t miblen, size_t i)
1178234370Sjasone{
1179234370Sjasone
1180234370Sjasone	if (i > nlclasses)
1181234370Sjasone		return (NULL);
1182234370Sjasone	return (super_arenas_lrun_i_node);
1183234370Sjasone}
1184234370Sjasone
1185234370SjasoneCTL_RO_NL_GEN(arenas_narenas, narenas, unsigned)
1186234370Sjasone
1187234370Sjasonestatic int
1188234370Sjasonearenas_initialized_ctl(const size_t *mib, size_t miblen, void *oldp,
1189234370Sjasone    size_t *oldlenp, void *newp, size_t newlen)
1190234370Sjasone{
1191234370Sjasone	int ret;
1192234370Sjasone	unsigned nread, i;
1193234370Sjasone
1194234370Sjasone	malloc_mutex_lock(&ctl_mtx);
1195234370Sjasone	READONLY();
1196234370Sjasone	if (*oldlenp != narenas * sizeof(bool)) {
1197234370Sjasone		ret = EINVAL;
1198234370Sjasone		nread = (*oldlenp < narenas * sizeof(bool))
1199234370Sjasone		    ? (*oldlenp / sizeof(bool)) : narenas;
1200234370Sjasone	} else {
1201234370Sjasone		ret = 0;
1202234370Sjasone		nread = narenas;
1203234370Sjasone	}
1204234370Sjasone
1205234370Sjasone	for (i = 0; i < nread; i++)
1206234370Sjasone		((bool *)oldp)[i] = ctl_stats.arenas[i].initialized;
1207234370Sjasone
1208234370Sjasonelabel_return:
1209234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
1210234370Sjasone	return (ret);
1211234370Sjasone}
1212234370Sjasone
1213234370SjasoneCTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
1214234370SjasoneCTL_RO_NL_GEN(arenas_page, PAGE, size_t)
1215234370SjasoneCTL_RO_NL_CGEN(config_tcache, arenas_tcache_max, tcache_maxclass, size_t)
1216234370SjasoneCTL_RO_NL_GEN(arenas_nbins, NBINS, unsigned)
1217234370SjasoneCTL_RO_NL_CGEN(config_tcache, arenas_nhbins, nhbins, unsigned)
1218234370SjasoneCTL_RO_NL_GEN(arenas_nlruns, nlclasses, size_t)
1219234370Sjasone
1220234370Sjasonestatic int
1221234370Sjasonearenas_purge_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1222234370Sjasone    void *newp, size_t newlen)
1223234370Sjasone{
1224234370Sjasone	int ret;
1225234370Sjasone	unsigned arena;
1226234370Sjasone
1227234370Sjasone	WRITEONLY();
1228234370Sjasone	arena = UINT_MAX;
1229234370Sjasone	WRITE(arena, unsigned);
1230234370Sjasone	if (newp != NULL && arena >= narenas) {
1231234370Sjasone		ret = EFAULT;
1232234370Sjasone		goto label_return;
1233234370Sjasone	} else {
1234235238Sjasone		VARIABLE_ARRAY(arena_t *, tarenas, narenas);
1235234370Sjasone
1236234370Sjasone		malloc_mutex_lock(&arenas_lock);
1237234370Sjasone		memcpy(tarenas, arenas, sizeof(arena_t *) * narenas);
1238234370Sjasone		malloc_mutex_unlock(&arenas_lock);
1239234370Sjasone
1240234370Sjasone		if (arena == UINT_MAX) {
1241234370Sjasone			unsigned i;
1242234370Sjasone			for (i = 0; i < narenas; i++) {
1243234370Sjasone				if (tarenas[i] != NULL)
1244234370Sjasone					arena_purge_all(tarenas[i]);
1245234370Sjasone			}
1246234370Sjasone		} else {
1247234370Sjasone			assert(arena < narenas);
1248234370Sjasone			if (tarenas[arena] != NULL)
1249234370Sjasone				arena_purge_all(tarenas[arena]);
1250234370Sjasone		}
1251234370Sjasone	}
1252234370Sjasone
1253234370Sjasone	ret = 0;
1254234370Sjasonelabel_return:
1255234370Sjasone	return (ret);
1256234370Sjasone}
1257234370Sjasone
1258234370Sjasone/******************************************************************************/
1259234370Sjasone
1260234370Sjasonestatic int
1261234370Sjasoneprof_active_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1262234370Sjasone    void *newp, size_t newlen)
1263234370Sjasone{
1264234370Sjasone	int ret;
1265234370Sjasone	bool oldval;
1266234370Sjasone
1267234370Sjasone	if (config_prof == false)
1268234370Sjasone		return (ENOENT);
1269234370Sjasone
1270234370Sjasone	malloc_mutex_lock(&ctl_mtx); /* Protect opt_prof_active. */
1271234370Sjasone	oldval = opt_prof_active;
1272234370Sjasone	if (newp != NULL) {
1273234370Sjasone		/*
1274234370Sjasone		 * The memory barriers will tend to make opt_prof_active
1275234370Sjasone		 * propagate faster on systems with weak memory ordering.
1276234370Sjasone		 */
1277234370Sjasone		mb_write();
1278234370Sjasone		WRITE(opt_prof_active, bool);
1279234370Sjasone		mb_write();
1280234370Sjasone	}
1281234370Sjasone	READ(oldval, bool);
1282234370Sjasone
1283234370Sjasone	ret = 0;
1284234370Sjasonelabel_return:
1285234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
1286234370Sjasone	return (ret);
1287234370Sjasone}
1288234370Sjasone
1289234370Sjasonestatic int
1290234370Sjasoneprof_dump_ctl(const size_t *mib, size_t miblen, void *oldp, size_t *oldlenp,
1291234370Sjasone    void *newp, size_t newlen)
1292234370Sjasone{
1293234370Sjasone	int ret;
1294234370Sjasone	const char *filename = NULL;
1295234370Sjasone
1296234370Sjasone	if (config_prof == false)
1297234370Sjasone		return (ENOENT);
1298234370Sjasone
1299234370Sjasone	WRITEONLY();
1300234370Sjasone	WRITE(filename, const char *);
1301234370Sjasone
1302234370Sjasone	if (prof_mdump(filename)) {
1303234370Sjasone		ret = EFAULT;
1304234370Sjasone		goto label_return;
1305234370Sjasone	}
1306234370Sjasone
1307234370Sjasone	ret = 0;
1308234370Sjasonelabel_return:
1309234370Sjasone	return (ret);
1310234370Sjasone}
1311234370Sjasone
1312234370SjasoneCTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
1313234370Sjasone
1314234370Sjasone/******************************************************************************/
1315234370Sjasone
1316234370SjasoneCTL_RO_CGEN(config_stats, stats_chunks_current, ctl_stats.chunks.current,
1317234370Sjasone    size_t)
1318234370SjasoneCTL_RO_CGEN(config_stats, stats_chunks_total, ctl_stats.chunks.total, uint64_t)
1319234370SjasoneCTL_RO_CGEN(config_stats, stats_chunks_high, ctl_stats.chunks.high, size_t)
1320234370SjasoneCTL_RO_CGEN(config_stats, stats_huge_allocated, huge_allocated, size_t)
1321234370SjasoneCTL_RO_CGEN(config_stats, stats_huge_nmalloc, huge_nmalloc, uint64_t)
1322234370SjasoneCTL_RO_CGEN(config_stats, stats_huge_ndalloc, huge_ndalloc, uint64_t)
1323234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
1324234370Sjasone    ctl_stats.arenas[mib[2]].allocated_small, size_t)
1325234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
1326234370Sjasone    ctl_stats.arenas[mib[2]].nmalloc_small, uint64_t)
1327234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
1328234370Sjasone    ctl_stats.arenas[mib[2]].ndalloc_small, uint64_t)
1329234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
1330234370Sjasone    ctl_stats.arenas[mib[2]].nrequests_small, uint64_t)
1331234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
1332234370Sjasone    ctl_stats.arenas[mib[2]].astats.allocated_large, size_t)
1333234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
1334234370Sjasone    ctl_stats.arenas[mib[2]].astats.nmalloc_large, uint64_t)
1335234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
1336234370Sjasone    ctl_stats.arenas[mib[2]].astats.ndalloc_large, uint64_t)
1337234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
1338234370Sjasone    ctl_stats.arenas[mib[2]].astats.nrequests_large, uint64_t)
1339234370Sjasone
1340234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_allocated,
1341234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].allocated, size_t)
1342234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
1343234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nmalloc, uint64_t)
1344234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
1345234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].ndalloc, uint64_t)
1346234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
1347234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nrequests, uint64_t)
1348234370SjasoneCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nfills,
1349234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nfills, uint64_t)
1350234370SjasoneCTL_RO_CGEN(config_stats && config_tcache, stats_arenas_i_bins_j_nflushes,
1351234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nflushes, uint64_t)
1352234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nruns,
1353234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].nruns, uint64_t)
1354234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreruns,
1355234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].reruns, uint64_t)
1356234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curruns,
1357234370Sjasone    ctl_stats.arenas[mib[2]].bstats[mib[4]].curruns, size_t)
1358234370Sjasone
1359235238Sjasoneconst ctl_named_node_t *
1360234370Sjasonestats_arenas_i_bins_j_index(const size_t *mib, size_t miblen, size_t j)
1361234370Sjasone{
1362234370Sjasone
1363234370Sjasone	if (j > NBINS)
1364234370Sjasone		return (NULL);
1365234370Sjasone	return (super_stats_arenas_i_bins_j_node);
1366234370Sjasone}
1367234370Sjasone
1368234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nmalloc,
1369234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].nmalloc, uint64_t)
1370234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_ndalloc,
1371234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].ndalloc, uint64_t)
1372234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_nrequests,
1373234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].nrequests, uint64_t)
1374234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_lruns_j_curruns,
1375234370Sjasone    ctl_stats.arenas[mib[2]].lstats[mib[4]].curruns, size_t)
1376234370Sjasone
1377235238Sjasoneconst ctl_named_node_t *
1378234370Sjasonestats_arenas_i_lruns_j_index(const size_t *mib, size_t miblen, size_t j)
1379234370Sjasone{
1380234370Sjasone
1381234370Sjasone	if (j > nlclasses)
1382234370Sjasone		return (NULL);
1383234370Sjasone	return (super_stats_arenas_i_lruns_j_node);
1384234370Sjasone}
1385234370Sjasone
1386234370SjasoneCTL_RO_GEN(stats_arenas_i_nthreads, ctl_stats.arenas[mib[2]].nthreads, unsigned)
1387234370SjasoneCTL_RO_GEN(stats_arenas_i_pactive, ctl_stats.arenas[mib[2]].pactive, size_t)
1388234370SjasoneCTL_RO_GEN(stats_arenas_i_pdirty, ctl_stats.arenas[mib[2]].pdirty, size_t)
1389234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
1390234370Sjasone    ctl_stats.arenas[mib[2]].astats.mapped, size_t)
1391234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_npurge,
1392234370Sjasone    ctl_stats.arenas[mib[2]].astats.npurge, uint64_t)
1393234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_nmadvise,
1394234370Sjasone    ctl_stats.arenas[mib[2]].astats.nmadvise, uint64_t)
1395234370SjasoneCTL_RO_CGEN(config_stats, stats_arenas_i_purged,
1396234370Sjasone    ctl_stats.arenas[mib[2]].astats.purged, uint64_t)
1397234370Sjasone
1398235238Sjasoneconst ctl_named_node_t *
1399234370Sjasonestats_arenas_i_index(const size_t *mib, size_t miblen, size_t i)
1400234370Sjasone{
1401235238Sjasone	const ctl_named_node_t * ret;
1402234370Sjasone
1403234370Sjasone	malloc_mutex_lock(&ctl_mtx);
1404234370Sjasone	if (ctl_stats.arenas[i].initialized == false) {
1405234370Sjasone		ret = NULL;
1406234370Sjasone		goto label_return;
1407234370Sjasone	}
1408234370Sjasone
1409234370Sjasone	ret = super_stats_arenas_i_node;
1410234370Sjasonelabel_return:
1411234370Sjasone	malloc_mutex_unlock(&ctl_mtx);
1412234370Sjasone	return (ret);
1413234370Sjasone}
1414234370Sjasone
1415234370SjasoneCTL_RO_CGEN(config_stats, stats_cactive, &stats_cactive, size_t *)
1416234370SjasoneCTL_RO_CGEN(config_stats, stats_allocated, ctl_stats.allocated, size_t)
1417234370SjasoneCTL_RO_CGEN(config_stats, stats_active, ctl_stats.active, size_t)
1418234370SjasoneCTL_RO_CGEN(config_stats, stats_mapped, ctl_stats.mapped, size_t)
1419