1a4bd5210SJason Evans #define JEMALLOC_CTL_C_
2b7eaed25SJason Evans #include "jemalloc/internal/jemalloc_preamble.h"
3b7eaed25SJason Evans #include "jemalloc/internal/jemalloc_internal_includes.h"
4b7eaed25SJason Evans
5b7eaed25SJason Evans #include "jemalloc/internal/assert.h"
6b7eaed25SJason Evans #include "jemalloc/internal/ctl.h"
7b7eaed25SJason Evans #include "jemalloc/internal/extent_dss.h"
8b7eaed25SJason Evans #include "jemalloc/internal/extent_mmap.h"
9b7eaed25SJason Evans #include "jemalloc/internal/mutex.h"
10b7eaed25SJason Evans #include "jemalloc/internal/nstime.h"
11*c5ad8142SEric van Gyzen #include "jemalloc/internal/sc.h"
12b7eaed25SJason Evans #include "jemalloc/internal/util.h"
13a4bd5210SJason Evans
14a4bd5210SJason Evans /******************************************************************************/
15a4bd5210SJason Evans /* Data. */
16a4bd5210SJason Evans
17a4bd5210SJason Evans /*
18a4bd5210SJason Evans * ctl_mtx protects the following:
19b7eaed25SJason Evans * - ctl_stats->*
20a4bd5210SJason Evans */
21a4bd5210SJason Evans static malloc_mutex_t ctl_mtx;
22a4bd5210SJason Evans static bool ctl_initialized;
23b7eaed25SJason Evans static ctl_stats_t *ctl_stats;
24b7eaed25SJason Evans static ctl_arenas_t *ctl_arenas;
25a4bd5210SJason Evans
26a4bd5210SJason Evans /******************************************************************************/
27e722f8f8SJason Evans /* Helpers for named and indexed nodes. */
28e722f8f8SJason Evans
29b7eaed25SJason Evans static const ctl_named_node_t *
ctl_named_node(const ctl_node_t * node)30b7eaed25SJason Evans ctl_named_node(const ctl_node_t *node) {
31e722f8f8SJason Evans return ((node->named) ? (const ctl_named_node_t *)node : NULL);
32e722f8f8SJason Evans }
33e722f8f8SJason Evans
34b7eaed25SJason Evans static const ctl_named_node_t *
ctl_named_children(const ctl_named_node_t * node,size_t index)35b7eaed25SJason Evans ctl_named_children(const ctl_named_node_t *node, size_t index) {
36e722f8f8SJason Evans const ctl_named_node_t *children = ctl_named_node(node->children);
37e722f8f8SJason Evans
38e722f8f8SJason Evans return (children ? &children[index] : NULL);
39e722f8f8SJason Evans }
40e722f8f8SJason Evans
41b7eaed25SJason Evans static const ctl_indexed_node_t *
ctl_indexed_node(const ctl_node_t * node)42b7eaed25SJason Evans ctl_indexed_node(const ctl_node_t *node) {
43d0e79aa3SJason Evans return (!node->named ? (const ctl_indexed_node_t *)node : NULL);
44e722f8f8SJason Evans }
45e722f8f8SJason Evans
46e722f8f8SJason Evans /******************************************************************************/
47a4bd5210SJason Evans /* Function prototypes for non-inline static functions. */
48a4bd5210SJason Evans
49a4bd5210SJason Evans #define CTL_PROTO(n) \
501f0a49e8SJason Evans static int n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
511f0a49e8SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen);
52a4bd5210SJason Evans
53a4bd5210SJason Evans #define INDEX_PROTO(n) \
541f0a49e8SJason Evans static const ctl_named_node_t *n##_index(tsdn_t *tsdn, \
551f0a49e8SJason Evans const size_t *mib, size_t miblen, size_t i);
56a4bd5210SJason Evans
57a4bd5210SJason Evans CTL_PROTO(version)
58a4bd5210SJason Evans CTL_PROTO(epoch)
59b7eaed25SJason Evans CTL_PROTO(background_thread)
600ef50b4eSJason Evans CTL_PROTO(max_background_threads)
61a4bd5210SJason Evans CTL_PROTO(thread_tcache_enabled)
62a4bd5210SJason Evans CTL_PROTO(thread_tcache_flush)
63d0e79aa3SJason Evans CTL_PROTO(thread_prof_name)
64d0e79aa3SJason Evans CTL_PROTO(thread_prof_active)
65a4bd5210SJason Evans CTL_PROTO(thread_arena)
66a4bd5210SJason Evans CTL_PROTO(thread_allocated)
67a4bd5210SJason Evans CTL_PROTO(thread_allocatedp)
68a4bd5210SJason Evans CTL_PROTO(thread_deallocated)
69a4bd5210SJason Evans CTL_PROTO(thread_deallocatedp)
70d0e79aa3SJason Evans CTL_PROTO(config_cache_oblivious)
71a4bd5210SJason Evans CTL_PROTO(config_debug)
72a4bd5210SJason Evans CTL_PROTO(config_fill)
73a4bd5210SJason Evans CTL_PROTO(config_lazy_lock)
74df0d881dSJason Evans CTL_PROTO(config_malloc_conf)
75*c5ad8142SEric van Gyzen CTL_PROTO(config_opt_safety_checks)
76a4bd5210SJason Evans CTL_PROTO(config_prof)
77a4bd5210SJason Evans CTL_PROTO(config_prof_libgcc)
78a4bd5210SJason Evans CTL_PROTO(config_prof_libunwind)
79a4bd5210SJason Evans CTL_PROTO(config_stats)
80a4bd5210SJason Evans CTL_PROTO(config_utrace)
81a4bd5210SJason Evans CTL_PROTO(config_xmalloc)
82a4bd5210SJason Evans CTL_PROTO(opt_abort)
83b7eaed25SJason Evans CTL_PROTO(opt_abort_conf)
84*c5ad8142SEric van Gyzen CTL_PROTO(opt_confirm_conf)
850ef50b4eSJason Evans CTL_PROTO(opt_metadata_thp)
86b7eaed25SJason Evans CTL_PROTO(opt_retain)
8782872ac0SJason Evans CTL_PROTO(opt_dss)
88a4bd5210SJason Evans CTL_PROTO(opt_narenas)
89b7eaed25SJason Evans CTL_PROTO(opt_percpu_arena)
90*c5ad8142SEric van Gyzen CTL_PROTO(opt_oversize_threshold)
91b7eaed25SJason Evans CTL_PROTO(opt_background_thread)
920ef50b4eSJason Evans CTL_PROTO(opt_max_background_threads)
93b7eaed25SJason Evans CTL_PROTO(opt_dirty_decay_ms)
94b7eaed25SJason Evans CTL_PROTO(opt_muzzy_decay_ms)
95a4bd5210SJason Evans CTL_PROTO(opt_stats_print)
96b7eaed25SJason Evans CTL_PROTO(opt_stats_print_opts)
97a4bd5210SJason Evans CTL_PROTO(opt_junk)
98a4bd5210SJason Evans CTL_PROTO(opt_zero)
99a4bd5210SJason Evans CTL_PROTO(opt_utrace)
100a4bd5210SJason Evans CTL_PROTO(opt_xmalloc)
101a4bd5210SJason Evans CTL_PROTO(opt_tcache)
1020ef50b4eSJason Evans CTL_PROTO(opt_thp)
1030ef50b4eSJason Evans CTL_PROTO(opt_lg_extent_max_active_fit)
104a4bd5210SJason Evans CTL_PROTO(opt_lg_tcache_max)
105a4bd5210SJason Evans CTL_PROTO(opt_prof)
106a4bd5210SJason Evans CTL_PROTO(opt_prof_prefix)
107a4bd5210SJason Evans CTL_PROTO(opt_prof_active)
108d0e79aa3SJason Evans CTL_PROTO(opt_prof_thread_active_init)
109a4bd5210SJason Evans CTL_PROTO(opt_lg_prof_sample)
110a4bd5210SJason Evans CTL_PROTO(opt_lg_prof_interval)
111a4bd5210SJason Evans CTL_PROTO(opt_prof_gdump)
1128ed34ab0SJason Evans CTL_PROTO(opt_prof_final)
113a4bd5210SJason Evans CTL_PROTO(opt_prof_leak)
114a4bd5210SJason Evans CTL_PROTO(opt_prof_accum)
115d0e79aa3SJason Evans CTL_PROTO(tcache_create)
116d0e79aa3SJason Evans CTL_PROTO(tcache_flush)
117d0e79aa3SJason Evans CTL_PROTO(tcache_destroy)
118b7eaed25SJason Evans CTL_PROTO(arena_i_initialized)
119df0d881dSJason Evans CTL_PROTO(arena_i_decay)
120b7eaed25SJason Evans CTL_PROTO(arena_i_purge)
1211f0a49e8SJason Evans CTL_PROTO(arena_i_reset)
122b7eaed25SJason Evans CTL_PROTO(arena_i_destroy)
12382872ac0SJason Evans CTL_PROTO(arena_i_dss)
124b7eaed25SJason Evans CTL_PROTO(arena_i_dirty_decay_ms)
125b7eaed25SJason Evans CTL_PROTO(arena_i_muzzy_decay_ms)
126b7eaed25SJason Evans CTL_PROTO(arena_i_extent_hooks)
1270ef50b4eSJason Evans CTL_PROTO(arena_i_retain_grow_limit)
12882872ac0SJason Evans INDEX_PROTO(arena_i)
129a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_size)
130a4bd5210SJason Evans CTL_PROTO(arenas_bin_i_nregs)
131b7eaed25SJason Evans CTL_PROTO(arenas_bin_i_slab_size)
132*c5ad8142SEric van Gyzen CTL_PROTO(arenas_bin_i_nshards)
133a4bd5210SJason Evans INDEX_PROTO(arenas_bin_i)
134b7eaed25SJason Evans CTL_PROTO(arenas_lextent_i_size)
135b7eaed25SJason Evans INDEX_PROTO(arenas_lextent_i)
136a4bd5210SJason Evans CTL_PROTO(arenas_narenas)
137b7eaed25SJason Evans CTL_PROTO(arenas_dirty_decay_ms)
138b7eaed25SJason Evans CTL_PROTO(arenas_muzzy_decay_ms)
139a4bd5210SJason Evans CTL_PROTO(arenas_quantum)
140a4bd5210SJason Evans CTL_PROTO(arenas_page)
141a4bd5210SJason Evans CTL_PROTO(arenas_tcache_max)
142a4bd5210SJason Evans CTL_PROTO(arenas_nbins)
143a4bd5210SJason Evans CTL_PROTO(arenas_nhbins)
144b7eaed25SJason Evans CTL_PROTO(arenas_nlextents)
145b7eaed25SJason Evans CTL_PROTO(arenas_create)
1460ef50b4eSJason Evans CTL_PROTO(arenas_lookup)
147d0e79aa3SJason Evans CTL_PROTO(prof_thread_active_init)
148a4bd5210SJason Evans CTL_PROTO(prof_active)
149a4bd5210SJason Evans CTL_PROTO(prof_dump)
150d0e79aa3SJason Evans CTL_PROTO(prof_gdump)
151d0e79aa3SJason Evans CTL_PROTO(prof_reset)
152a4bd5210SJason Evans CTL_PROTO(prof_interval)
153d0e79aa3SJason Evans CTL_PROTO(lg_prof_sample)
154*c5ad8142SEric van Gyzen CTL_PROTO(prof_log_start)
155*c5ad8142SEric van Gyzen CTL_PROTO(prof_log_stop)
156a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_allocated)
157a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_nmalloc)
158a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_ndalloc)
159a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_small_nrequests)
160*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_small_nfills)
161*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_small_nflushes)
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)
166*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_large_nfills)
167*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_large_nflushes)
168a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nmalloc)
169a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_ndalloc)
170a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nrequests)
171d0e79aa3SJason Evans CTL_PROTO(stats_arenas_i_bins_j_curregs)
172a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nfills)
173a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nflushes)
174b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nslabs)
175b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_bins_j_nreslabs)
176b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_bins_j_curslabs)
177*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_bins_j_nonfull_slabs)
178a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i_bins_j)
179b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_lextents_j_nmalloc)
180b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_lextents_j_ndalloc)
181b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_lextents_j_nrequests)
182b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_lextents_j_curlextents)
183b7eaed25SJason Evans INDEX_PROTO(stats_arenas_i_lextents_j)
184*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_extents_j_ndirty)
185*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_extents_j_nmuzzy)
186*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_extents_j_nretained)
187*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_extents_j_dirty_bytes)
188*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_extents_j_muzzy_bytes)
189*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_extents_j_retained_bytes)
190*c5ad8142SEric van Gyzen INDEX_PROTO(stats_arenas_i_extents_j)
191a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_nthreads)
192b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_uptime)
19382872ac0SJason Evans CTL_PROTO(stats_arenas_i_dss)
194b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_dirty_decay_ms)
195b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_muzzy_decay_ms)
196a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_pactive)
197a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_pdirty)
198b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_pmuzzy)
199a4bd5210SJason Evans CTL_PROTO(stats_arenas_i_mapped)
2001f0a49e8SJason Evans CTL_PROTO(stats_arenas_i_retained)
201*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_extent_avail)
202b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_dirty_npurge)
203b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_dirty_nmadvise)
204b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_dirty_purged)
205b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_muzzy_npurge)
206b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_muzzy_nmadvise)
207b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_muzzy_purged)
208b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_base)
209b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_internal)
2100ef50b4eSJason Evans CTL_PROTO(stats_arenas_i_metadata_thp)
211b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_tcache_bytes)
212b7eaed25SJason Evans CTL_PROTO(stats_arenas_i_resident)
213*c5ad8142SEric van Gyzen CTL_PROTO(stats_arenas_i_abandoned_vm)
214a4bd5210SJason Evans INDEX_PROTO(stats_arenas_i)
215a4bd5210SJason Evans CTL_PROTO(stats_allocated)
216a4bd5210SJason Evans CTL_PROTO(stats_active)
217b7eaed25SJason Evans CTL_PROTO(stats_background_thread_num_threads)
218b7eaed25SJason Evans CTL_PROTO(stats_background_thread_num_runs)
219b7eaed25SJason Evans CTL_PROTO(stats_background_thread_run_interval)
220d0e79aa3SJason Evans CTL_PROTO(stats_metadata)
2210ef50b4eSJason Evans CTL_PROTO(stats_metadata_thp)
222d0e79aa3SJason Evans CTL_PROTO(stats_resident)
223a4bd5210SJason Evans CTL_PROTO(stats_mapped)
2241f0a49e8SJason Evans CTL_PROTO(stats_retained)
225*c5ad8142SEric van Gyzen CTL_PROTO(experimental_hooks_install)
226*c5ad8142SEric van Gyzen CTL_PROTO(experimental_hooks_remove)
227*c5ad8142SEric van Gyzen CTL_PROTO(experimental_utilization_query)
228*c5ad8142SEric van Gyzen CTL_PROTO(experimental_utilization_batch_query)
229*c5ad8142SEric van Gyzen CTL_PROTO(experimental_arenas_i_pactivep)
230*c5ad8142SEric van Gyzen INDEX_PROTO(experimental_arenas_i)
231a4bd5210SJason Evans
232b7eaed25SJason Evans #define MUTEX_STATS_CTL_PROTO_GEN(n) \
233b7eaed25SJason Evans CTL_PROTO(stats_##n##_num_ops) \
234b7eaed25SJason Evans CTL_PROTO(stats_##n##_num_wait) \
235b7eaed25SJason Evans CTL_PROTO(stats_##n##_num_spin_acq) \
236b7eaed25SJason Evans CTL_PROTO(stats_##n##_num_owner_switch) \
237b7eaed25SJason Evans CTL_PROTO(stats_##n##_total_wait_time) \
238b7eaed25SJason Evans CTL_PROTO(stats_##n##_max_wait_time) \
239b7eaed25SJason Evans CTL_PROTO(stats_##n##_max_num_thds)
240b7eaed25SJason Evans
241b7eaed25SJason Evans /* Global mutexes. */
242b7eaed25SJason Evans #define OP(mtx) MUTEX_STATS_CTL_PROTO_GEN(mutexes_##mtx)
243b7eaed25SJason Evans MUTEX_PROF_GLOBAL_MUTEXES
244b7eaed25SJason Evans #undef OP
245b7eaed25SJason Evans
246b7eaed25SJason Evans /* Per arena mutexes. */
247b7eaed25SJason Evans #define OP(mtx) MUTEX_STATS_CTL_PROTO_GEN(arenas_i_mutexes_##mtx)
248b7eaed25SJason Evans MUTEX_PROF_ARENA_MUTEXES
249b7eaed25SJason Evans #undef OP
250b7eaed25SJason Evans
251b7eaed25SJason Evans /* Arena bin mutexes. */
252b7eaed25SJason Evans MUTEX_STATS_CTL_PROTO_GEN(arenas_i_bins_j_mutex)
253b7eaed25SJason Evans #undef MUTEX_STATS_CTL_PROTO_GEN
254b7eaed25SJason Evans
255b7eaed25SJason Evans CTL_PROTO(stats_mutexes_reset)
256b7eaed25SJason Evans
257a4bd5210SJason Evans /******************************************************************************/
258a4bd5210SJason Evans /* mallctl tree. */
259a4bd5210SJason Evans
260e722f8f8SJason Evans #define NAME(n) {true}, n
261e722f8f8SJason Evans #define CHILD(t, c) \
262e722f8f8SJason Evans sizeof(c##_node) / sizeof(ctl_##t##_node_t), \
263e722f8f8SJason Evans (ctl_node_t *)c##_node, \
264e722f8f8SJason Evans NULL
265e722f8f8SJason Evans #define CTL(c) 0, NULL, c##_ctl
266a4bd5210SJason Evans
267a4bd5210SJason Evans /*
268a4bd5210SJason Evans * Only handles internal indexed nodes, since there are currently no external
269a4bd5210SJason Evans * ones.
270a4bd5210SJason Evans */
271e722f8f8SJason Evans #define INDEX(i) {false}, i##_index
272a4bd5210SJason Evans
273d0e79aa3SJason Evans static const ctl_named_node_t thread_tcache_node[] = {
274a4bd5210SJason Evans {NAME("enabled"), CTL(thread_tcache_enabled)},
275a4bd5210SJason Evans {NAME("flush"), CTL(thread_tcache_flush)}
276a4bd5210SJason Evans };
277a4bd5210SJason Evans
278d0e79aa3SJason Evans static const ctl_named_node_t thread_prof_node[] = {
279d0e79aa3SJason Evans {NAME("name"), CTL(thread_prof_name)},
280d0e79aa3SJason Evans {NAME("active"), CTL(thread_prof_active)}
281d0e79aa3SJason Evans };
282d0e79aa3SJason Evans
283e722f8f8SJason Evans static const ctl_named_node_t thread_node[] = {
284a4bd5210SJason Evans {NAME("arena"), CTL(thread_arena)},
285a4bd5210SJason Evans {NAME("allocated"), CTL(thread_allocated)},
286a4bd5210SJason Evans {NAME("allocatedp"), CTL(thread_allocatedp)},
287a4bd5210SJason Evans {NAME("deallocated"), CTL(thread_deallocated)},
288a4bd5210SJason Evans {NAME("deallocatedp"), CTL(thread_deallocatedp)},
289d0e79aa3SJason Evans {NAME("tcache"), CHILD(named, thread_tcache)},
290d0e79aa3SJason Evans {NAME("prof"), CHILD(named, thread_prof)}
291a4bd5210SJason Evans };
292a4bd5210SJason Evans
293e722f8f8SJason Evans static const ctl_named_node_t config_node[] = {
294d0e79aa3SJason Evans {NAME("cache_oblivious"), CTL(config_cache_oblivious)},
295a4bd5210SJason Evans {NAME("debug"), CTL(config_debug)},
296a4bd5210SJason Evans {NAME("fill"), CTL(config_fill)},
297a4bd5210SJason Evans {NAME("lazy_lock"), CTL(config_lazy_lock)},
298df0d881dSJason Evans {NAME("malloc_conf"), CTL(config_malloc_conf)},
299*c5ad8142SEric van Gyzen {NAME("opt_safety_checks"), CTL(config_opt_safety_checks)},
300a4bd5210SJason Evans {NAME("prof"), CTL(config_prof)},
301a4bd5210SJason Evans {NAME("prof_libgcc"), CTL(config_prof_libgcc)},
302a4bd5210SJason Evans {NAME("prof_libunwind"), CTL(config_prof_libunwind)},
303a4bd5210SJason Evans {NAME("stats"), CTL(config_stats)},
304a4bd5210SJason Evans {NAME("utrace"), CTL(config_utrace)},
305a4bd5210SJason Evans {NAME("xmalloc"), CTL(config_xmalloc)}
306a4bd5210SJason Evans };
307a4bd5210SJason Evans
308e722f8f8SJason Evans static const ctl_named_node_t opt_node[] = {
309a4bd5210SJason Evans {NAME("abort"), CTL(opt_abort)},
310b7eaed25SJason Evans {NAME("abort_conf"), CTL(opt_abort_conf)},
311*c5ad8142SEric van Gyzen {NAME("confirm_conf"), CTL(opt_confirm_conf)},
3120ef50b4eSJason Evans {NAME("metadata_thp"), CTL(opt_metadata_thp)},
313b7eaed25SJason Evans {NAME("retain"), CTL(opt_retain)},
31482872ac0SJason Evans {NAME("dss"), CTL(opt_dss)},
315a4bd5210SJason Evans {NAME("narenas"), CTL(opt_narenas)},
316b7eaed25SJason Evans {NAME("percpu_arena"), CTL(opt_percpu_arena)},
317*c5ad8142SEric van Gyzen {NAME("oversize_threshold"), CTL(opt_oversize_threshold)},
318b7eaed25SJason Evans {NAME("background_thread"), CTL(opt_background_thread)},
3190ef50b4eSJason Evans {NAME("max_background_threads"), CTL(opt_max_background_threads)},
320b7eaed25SJason Evans {NAME("dirty_decay_ms"), CTL(opt_dirty_decay_ms)},
321b7eaed25SJason Evans {NAME("muzzy_decay_ms"), CTL(opt_muzzy_decay_ms)},
322a4bd5210SJason Evans {NAME("stats_print"), CTL(opt_stats_print)},
323b7eaed25SJason Evans {NAME("stats_print_opts"), CTL(opt_stats_print_opts)},
324a4bd5210SJason Evans {NAME("junk"), CTL(opt_junk)},
325a4bd5210SJason Evans {NAME("zero"), CTL(opt_zero)},
326a4bd5210SJason Evans {NAME("utrace"), CTL(opt_utrace)},
327a4bd5210SJason Evans {NAME("xmalloc"), CTL(opt_xmalloc)},
328a4bd5210SJason Evans {NAME("tcache"), CTL(opt_tcache)},
3290ef50b4eSJason Evans {NAME("thp"), CTL(opt_thp)},
3300ef50b4eSJason Evans {NAME("lg_extent_max_active_fit"), CTL(opt_lg_extent_max_active_fit)},
331a4bd5210SJason Evans {NAME("lg_tcache_max"), CTL(opt_lg_tcache_max)},
332a4bd5210SJason Evans {NAME("prof"), CTL(opt_prof)},
333a4bd5210SJason Evans {NAME("prof_prefix"), CTL(opt_prof_prefix)},
334a4bd5210SJason Evans {NAME("prof_active"), CTL(opt_prof_active)},
335d0e79aa3SJason Evans {NAME("prof_thread_active_init"), CTL(opt_prof_thread_active_init)},
336a4bd5210SJason Evans {NAME("lg_prof_sample"), CTL(opt_lg_prof_sample)},
337a4bd5210SJason Evans {NAME("lg_prof_interval"), CTL(opt_lg_prof_interval)},
338a4bd5210SJason Evans {NAME("prof_gdump"), CTL(opt_prof_gdump)},
3398ed34ab0SJason Evans {NAME("prof_final"), CTL(opt_prof_final)},
340a4bd5210SJason Evans {NAME("prof_leak"), CTL(opt_prof_leak)},
341a4bd5210SJason Evans {NAME("prof_accum"), CTL(opt_prof_accum)}
342a4bd5210SJason Evans };
343a4bd5210SJason Evans
344d0e79aa3SJason Evans static const ctl_named_node_t tcache_node[] = {
345d0e79aa3SJason Evans {NAME("create"), CTL(tcache_create)},
346d0e79aa3SJason Evans {NAME("flush"), CTL(tcache_flush)},
347d0e79aa3SJason Evans {NAME("destroy"), CTL(tcache_destroy)}
348d0e79aa3SJason Evans };
349d0e79aa3SJason Evans
35082872ac0SJason Evans static const ctl_named_node_t arena_i_node[] = {
351b7eaed25SJason Evans {NAME("initialized"), CTL(arena_i_initialized)},
352df0d881dSJason Evans {NAME("decay"), CTL(arena_i_decay)},
353b7eaed25SJason Evans {NAME("purge"), CTL(arena_i_purge)},
3541f0a49e8SJason Evans {NAME("reset"), CTL(arena_i_reset)},
355b7eaed25SJason Evans {NAME("destroy"), CTL(arena_i_destroy)},
356d0e79aa3SJason Evans {NAME("dss"), CTL(arena_i_dss)},
357b7eaed25SJason Evans {NAME("dirty_decay_ms"), CTL(arena_i_dirty_decay_ms)},
358b7eaed25SJason Evans {NAME("muzzy_decay_ms"), CTL(arena_i_muzzy_decay_ms)},
3590ef50b4eSJason Evans {NAME("extent_hooks"), CTL(arena_i_extent_hooks)},
3600ef50b4eSJason Evans {NAME("retain_grow_limit"), CTL(arena_i_retain_grow_limit)}
36182872ac0SJason Evans };
36282872ac0SJason Evans static const ctl_named_node_t super_arena_i_node[] = {
36382872ac0SJason Evans {NAME(""), CHILD(named, arena_i)}
36482872ac0SJason Evans };
36582872ac0SJason Evans
36682872ac0SJason Evans static const ctl_indexed_node_t arena_node[] = {
36782872ac0SJason Evans {INDEX(arena_i)}
36882872ac0SJason Evans };
36982872ac0SJason Evans
370e722f8f8SJason Evans static const ctl_named_node_t arenas_bin_i_node[] = {
371a4bd5210SJason Evans {NAME("size"), CTL(arenas_bin_i_size)},
372a4bd5210SJason Evans {NAME("nregs"), CTL(arenas_bin_i_nregs)},
373*c5ad8142SEric van Gyzen {NAME("slab_size"), CTL(arenas_bin_i_slab_size)},
374*c5ad8142SEric van Gyzen {NAME("nshards"), CTL(arenas_bin_i_nshards)}
375a4bd5210SJason Evans };
376e722f8f8SJason Evans static const ctl_named_node_t super_arenas_bin_i_node[] = {
377e722f8f8SJason Evans {NAME(""), CHILD(named, arenas_bin_i)}
378a4bd5210SJason Evans };
379a4bd5210SJason Evans
380e722f8f8SJason Evans static const ctl_indexed_node_t arenas_bin_node[] = {
381a4bd5210SJason Evans {INDEX(arenas_bin_i)}
382a4bd5210SJason Evans };
383a4bd5210SJason Evans
384b7eaed25SJason Evans static const ctl_named_node_t arenas_lextent_i_node[] = {
385b7eaed25SJason Evans {NAME("size"), CTL(arenas_lextent_i_size)}
386a4bd5210SJason Evans };
387b7eaed25SJason Evans static const ctl_named_node_t super_arenas_lextent_i_node[] = {
388b7eaed25SJason Evans {NAME(""), CHILD(named, arenas_lextent_i)}
389a4bd5210SJason Evans };
390a4bd5210SJason Evans
391b7eaed25SJason Evans static const ctl_indexed_node_t arenas_lextent_node[] = {
392b7eaed25SJason Evans {INDEX(arenas_lextent_i)}
393d0e79aa3SJason Evans };
394d0e79aa3SJason Evans
395e722f8f8SJason Evans static const ctl_named_node_t arenas_node[] = {
396a4bd5210SJason Evans {NAME("narenas"), CTL(arenas_narenas)},
397b7eaed25SJason Evans {NAME("dirty_decay_ms"), CTL(arenas_dirty_decay_ms)},
398b7eaed25SJason Evans {NAME("muzzy_decay_ms"), CTL(arenas_muzzy_decay_ms)},
399a4bd5210SJason Evans {NAME("quantum"), CTL(arenas_quantum)},
400a4bd5210SJason Evans {NAME("page"), CTL(arenas_page)},
401a4bd5210SJason Evans {NAME("tcache_max"), CTL(arenas_tcache_max)},
402a4bd5210SJason Evans {NAME("nbins"), CTL(arenas_nbins)},
403a4bd5210SJason Evans {NAME("nhbins"), CTL(arenas_nhbins)},
404e722f8f8SJason Evans {NAME("bin"), CHILD(indexed, arenas_bin)},
405b7eaed25SJason Evans {NAME("nlextents"), CTL(arenas_nlextents)},
406b7eaed25SJason Evans {NAME("lextent"), CHILD(indexed, arenas_lextent)},
4070ef50b4eSJason Evans {NAME("create"), CTL(arenas_create)},
4080ef50b4eSJason Evans {NAME("lookup"), CTL(arenas_lookup)}
409a4bd5210SJason Evans };
410a4bd5210SJason Evans
411e722f8f8SJason Evans static const ctl_named_node_t prof_node[] = {
412d0e79aa3SJason Evans {NAME("thread_active_init"), CTL(prof_thread_active_init)},
413a4bd5210SJason Evans {NAME("active"), CTL(prof_active)},
414a4bd5210SJason Evans {NAME("dump"), CTL(prof_dump)},
415d0e79aa3SJason Evans {NAME("gdump"), CTL(prof_gdump)},
416d0e79aa3SJason Evans {NAME("reset"), CTL(prof_reset)},
417d0e79aa3SJason Evans {NAME("interval"), CTL(prof_interval)},
418*c5ad8142SEric van Gyzen {NAME("lg_sample"), CTL(lg_prof_sample)},
419*c5ad8142SEric van Gyzen {NAME("log_start"), CTL(prof_log_start)},
420*c5ad8142SEric van Gyzen {NAME("log_stop"), CTL(prof_log_stop)}
421a4bd5210SJason Evans };
422e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_small_node[] = {
423a4bd5210SJason Evans {NAME("allocated"), CTL(stats_arenas_i_small_allocated)},
424a4bd5210SJason Evans {NAME("nmalloc"), CTL(stats_arenas_i_small_nmalloc)},
425a4bd5210SJason Evans {NAME("ndalloc"), CTL(stats_arenas_i_small_ndalloc)},
426*c5ad8142SEric van Gyzen {NAME("nrequests"), CTL(stats_arenas_i_small_nrequests)},
427*c5ad8142SEric van Gyzen {NAME("nfills"), CTL(stats_arenas_i_small_nfills)},
428*c5ad8142SEric van Gyzen {NAME("nflushes"), CTL(stats_arenas_i_small_nflushes)}
429a4bd5210SJason Evans };
430a4bd5210SJason Evans
431e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_large_node[] = {
432a4bd5210SJason Evans {NAME("allocated"), CTL(stats_arenas_i_large_allocated)},
433a4bd5210SJason Evans {NAME("nmalloc"), CTL(stats_arenas_i_large_nmalloc)},
434a4bd5210SJason Evans {NAME("ndalloc"), CTL(stats_arenas_i_large_ndalloc)},
435*c5ad8142SEric van Gyzen {NAME("nrequests"), CTL(stats_arenas_i_large_nrequests)},
436*c5ad8142SEric van Gyzen {NAME("nfills"), CTL(stats_arenas_i_large_nfills)},
437*c5ad8142SEric van Gyzen {NAME("nflushes"), CTL(stats_arenas_i_large_nflushes)}
438a4bd5210SJason Evans };
439a4bd5210SJason Evans
440b7eaed25SJason Evans #define MUTEX_PROF_DATA_NODE(prefix) \
441b7eaed25SJason Evans static const ctl_named_node_t stats_##prefix##_node[] = { \
442b7eaed25SJason Evans {NAME("num_ops"), \
443b7eaed25SJason Evans CTL(stats_##prefix##_num_ops)}, \
444b7eaed25SJason Evans {NAME("num_wait"), \
445b7eaed25SJason Evans CTL(stats_##prefix##_num_wait)}, \
446b7eaed25SJason Evans {NAME("num_spin_acq"), \
447b7eaed25SJason Evans CTL(stats_##prefix##_num_spin_acq)}, \
448b7eaed25SJason Evans {NAME("num_owner_switch"), \
449b7eaed25SJason Evans CTL(stats_##prefix##_num_owner_switch)}, \
450b7eaed25SJason Evans {NAME("total_wait_time"), \
451b7eaed25SJason Evans CTL(stats_##prefix##_total_wait_time)}, \
452b7eaed25SJason Evans {NAME("max_wait_time"), \
453b7eaed25SJason Evans CTL(stats_##prefix##_max_wait_time)}, \
454b7eaed25SJason Evans {NAME("max_num_thds"), \
455b7eaed25SJason Evans CTL(stats_##prefix##_max_num_thds)} \
456b7eaed25SJason Evans /* Note that # of current waiting thread not provided. */ \
457d0e79aa3SJason Evans };
458d0e79aa3SJason Evans
459b7eaed25SJason Evans MUTEX_PROF_DATA_NODE(arenas_i_bins_j_mutex)
460b7eaed25SJason Evans
461e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_bins_j_node[] = {
462a4bd5210SJason Evans {NAME("nmalloc"), CTL(stats_arenas_i_bins_j_nmalloc)},
463a4bd5210SJason Evans {NAME("ndalloc"), CTL(stats_arenas_i_bins_j_ndalloc)},
464a4bd5210SJason Evans {NAME("nrequests"), CTL(stats_arenas_i_bins_j_nrequests)},
465d0e79aa3SJason Evans {NAME("curregs"), CTL(stats_arenas_i_bins_j_curregs)},
466a4bd5210SJason Evans {NAME("nfills"), CTL(stats_arenas_i_bins_j_nfills)},
467a4bd5210SJason Evans {NAME("nflushes"), CTL(stats_arenas_i_bins_j_nflushes)},
468b7eaed25SJason Evans {NAME("nslabs"), CTL(stats_arenas_i_bins_j_nslabs)},
469b7eaed25SJason Evans {NAME("nreslabs"), CTL(stats_arenas_i_bins_j_nreslabs)},
470b7eaed25SJason Evans {NAME("curslabs"), CTL(stats_arenas_i_bins_j_curslabs)},
471*c5ad8142SEric van Gyzen {NAME("nonfull_slabs"), CTL(stats_arenas_i_bins_j_nonfull_slabs)},
472b7eaed25SJason Evans {NAME("mutex"), CHILD(named, stats_arenas_i_bins_j_mutex)}
473a4bd5210SJason Evans };
474b7eaed25SJason Evans
475e722f8f8SJason Evans static const ctl_named_node_t super_stats_arenas_i_bins_j_node[] = {
476e722f8f8SJason Evans {NAME(""), CHILD(named, stats_arenas_i_bins_j)}
477a4bd5210SJason Evans };
478a4bd5210SJason Evans
479e722f8f8SJason Evans static const ctl_indexed_node_t stats_arenas_i_bins_node[] = {
480a4bd5210SJason Evans {INDEX(stats_arenas_i_bins_j)}
481a4bd5210SJason Evans };
482a4bd5210SJason Evans
483b7eaed25SJason Evans static const ctl_named_node_t stats_arenas_i_lextents_j_node[] = {
484b7eaed25SJason Evans {NAME("nmalloc"), CTL(stats_arenas_i_lextents_j_nmalloc)},
485b7eaed25SJason Evans {NAME("ndalloc"), CTL(stats_arenas_i_lextents_j_ndalloc)},
486b7eaed25SJason Evans {NAME("nrequests"), CTL(stats_arenas_i_lextents_j_nrequests)},
487b7eaed25SJason Evans {NAME("curlextents"), CTL(stats_arenas_i_lextents_j_curlextents)}
488a4bd5210SJason Evans };
489b7eaed25SJason Evans static const ctl_named_node_t super_stats_arenas_i_lextents_j_node[] = {
490b7eaed25SJason Evans {NAME(""), CHILD(named, stats_arenas_i_lextents_j)}
491a4bd5210SJason Evans };
492a4bd5210SJason Evans
493b7eaed25SJason Evans static const ctl_indexed_node_t stats_arenas_i_lextents_node[] = {
494b7eaed25SJason Evans {INDEX(stats_arenas_i_lextents_j)}
495a4bd5210SJason Evans };
496a4bd5210SJason Evans
497*c5ad8142SEric van Gyzen static const ctl_named_node_t stats_arenas_i_extents_j_node[] = {
498*c5ad8142SEric van Gyzen {NAME("ndirty"), CTL(stats_arenas_i_extents_j_ndirty)},
499*c5ad8142SEric van Gyzen {NAME("nmuzzy"), CTL(stats_arenas_i_extents_j_nmuzzy)},
500*c5ad8142SEric van Gyzen {NAME("nretained"), CTL(stats_arenas_i_extents_j_nretained)},
501*c5ad8142SEric van Gyzen {NAME("dirty_bytes"), CTL(stats_arenas_i_extents_j_dirty_bytes)},
502*c5ad8142SEric van Gyzen {NAME("muzzy_bytes"), CTL(stats_arenas_i_extents_j_muzzy_bytes)},
503*c5ad8142SEric van Gyzen {NAME("retained_bytes"), CTL(stats_arenas_i_extents_j_retained_bytes)}
504*c5ad8142SEric van Gyzen };
505*c5ad8142SEric van Gyzen
506*c5ad8142SEric van Gyzen static const ctl_named_node_t super_stats_arenas_i_extents_j_node[] = {
507*c5ad8142SEric van Gyzen {NAME(""), CHILD(named, stats_arenas_i_extents_j)}
508*c5ad8142SEric van Gyzen };
509*c5ad8142SEric van Gyzen
510*c5ad8142SEric van Gyzen static const ctl_indexed_node_t stats_arenas_i_extents_node[] = {
511*c5ad8142SEric van Gyzen {INDEX(stats_arenas_i_extents_j)}
512*c5ad8142SEric van Gyzen };
513*c5ad8142SEric van Gyzen
514b7eaed25SJason Evans #define OP(mtx) MUTEX_PROF_DATA_NODE(arenas_i_mutexes_##mtx)
515b7eaed25SJason Evans MUTEX_PROF_ARENA_MUTEXES
516b7eaed25SJason Evans #undef OP
517d0e79aa3SJason Evans
518b7eaed25SJason Evans static const ctl_named_node_t stats_arenas_i_mutexes_node[] = {
519b7eaed25SJason Evans #define OP(mtx) {NAME(#mtx), CHILD(named, stats_arenas_i_mutexes_##mtx)},
520b7eaed25SJason Evans MUTEX_PROF_ARENA_MUTEXES
521b7eaed25SJason Evans #undef OP
522d0e79aa3SJason Evans };
523d0e79aa3SJason Evans
524e722f8f8SJason Evans static const ctl_named_node_t stats_arenas_i_node[] = {
525a4bd5210SJason Evans {NAME("nthreads"), CTL(stats_arenas_i_nthreads)},
526b7eaed25SJason Evans {NAME("uptime"), CTL(stats_arenas_i_uptime)},
52782872ac0SJason Evans {NAME("dss"), CTL(stats_arenas_i_dss)},
528b7eaed25SJason Evans {NAME("dirty_decay_ms"), CTL(stats_arenas_i_dirty_decay_ms)},
529b7eaed25SJason Evans {NAME("muzzy_decay_ms"), CTL(stats_arenas_i_muzzy_decay_ms)},
530a4bd5210SJason Evans {NAME("pactive"), CTL(stats_arenas_i_pactive)},
531a4bd5210SJason Evans {NAME("pdirty"), CTL(stats_arenas_i_pdirty)},
532b7eaed25SJason Evans {NAME("pmuzzy"), CTL(stats_arenas_i_pmuzzy)},
533a4bd5210SJason Evans {NAME("mapped"), CTL(stats_arenas_i_mapped)},
5341f0a49e8SJason Evans {NAME("retained"), CTL(stats_arenas_i_retained)},
535*c5ad8142SEric van Gyzen {NAME("extent_avail"), CTL(stats_arenas_i_extent_avail)},
536b7eaed25SJason Evans {NAME("dirty_npurge"), CTL(stats_arenas_i_dirty_npurge)},
537b7eaed25SJason Evans {NAME("dirty_nmadvise"), CTL(stats_arenas_i_dirty_nmadvise)},
538b7eaed25SJason Evans {NAME("dirty_purged"), CTL(stats_arenas_i_dirty_purged)},
539b7eaed25SJason Evans {NAME("muzzy_npurge"), CTL(stats_arenas_i_muzzy_npurge)},
540b7eaed25SJason Evans {NAME("muzzy_nmadvise"), CTL(stats_arenas_i_muzzy_nmadvise)},
541b7eaed25SJason Evans {NAME("muzzy_purged"), CTL(stats_arenas_i_muzzy_purged)},
542b7eaed25SJason Evans {NAME("base"), CTL(stats_arenas_i_base)},
543b7eaed25SJason Evans {NAME("internal"), CTL(stats_arenas_i_internal)},
5440ef50b4eSJason Evans {NAME("metadata_thp"), CTL(stats_arenas_i_metadata_thp)},
545b7eaed25SJason Evans {NAME("tcache_bytes"), CTL(stats_arenas_i_tcache_bytes)},
546b7eaed25SJason Evans {NAME("resident"), CTL(stats_arenas_i_resident)},
547*c5ad8142SEric van Gyzen {NAME("abandoned_vm"), CTL(stats_arenas_i_abandoned_vm)},
548e722f8f8SJason Evans {NAME("small"), CHILD(named, stats_arenas_i_small)},
549e722f8f8SJason Evans {NAME("large"), CHILD(named, stats_arenas_i_large)},
550e722f8f8SJason Evans {NAME("bins"), CHILD(indexed, stats_arenas_i_bins)},
551b7eaed25SJason Evans {NAME("lextents"), CHILD(indexed, stats_arenas_i_lextents)},
552*c5ad8142SEric van Gyzen {NAME("extents"), CHILD(indexed, stats_arenas_i_extents)},
553b7eaed25SJason Evans {NAME("mutexes"), CHILD(named, stats_arenas_i_mutexes)}
554a4bd5210SJason Evans };
555e722f8f8SJason Evans static const ctl_named_node_t super_stats_arenas_i_node[] = {
556e722f8f8SJason Evans {NAME(""), CHILD(named, stats_arenas_i)}
557a4bd5210SJason Evans };
558a4bd5210SJason Evans
559e722f8f8SJason Evans static const ctl_indexed_node_t stats_arenas_node[] = {
560a4bd5210SJason Evans {INDEX(stats_arenas_i)}
561a4bd5210SJason Evans };
562a4bd5210SJason Evans
563b7eaed25SJason Evans static const ctl_named_node_t stats_background_thread_node[] = {
564b7eaed25SJason Evans {NAME("num_threads"), CTL(stats_background_thread_num_threads)},
565b7eaed25SJason Evans {NAME("num_runs"), CTL(stats_background_thread_num_runs)},
566b7eaed25SJason Evans {NAME("run_interval"), CTL(stats_background_thread_run_interval)}
567b7eaed25SJason Evans };
568b7eaed25SJason Evans
569b7eaed25SJason Evans #define OP(mtx) MUTEX_PROF_DATA_NODE(mutexes_##mtx)
570b7eaed25SJason Evans MUTEX_PROF_GLOBAL_MUTEXES
571b7eaed25SJason Evans #undef OP
572b7eaed25SJason Evans
573b7eaed25SJason Evans static const ctl_named_node_t stats_mutexes_node[] = {
574b7eaed25SJason Evans #define OP(mtx) {NAME(#mtx), CHILD(named, stats_mutexes_##mtx)},
575b7eaed25SJason Evans MUTEX_PROF_GLOBAL_MUTEXES
576b7eaed25SJason Evans #undef OP
577b7eaed25SJason Evans {NAME("reset"), CTL(stats_mutexes_reset)}
578b7eaed25SJason Evans };
579b7eaed25SJason Evans #undef MUTEX_PROF_DATA_NODE
580b7eaed25SJason Evans
581e722f8f8SJason Evans static const ctl_named_node_t stats_node[] = {
582a4bd5210SJason Evans {NAME("allocated"), CTL(stats_allocated)},
583a4bd5210SJason Evans {NAME("active"), CTL(stats_active)},
584d0e79aa3SJason Evans {NAME("metadata"), CTL(stats_metadata)},
5850ef50b4eSJason Evans {NAME("metadata_thp"), CTL(stats_metadata_thp)},
586d0e79aa3SJason Evans {NAME("resident"), CTL(stats_resident)},
587a4bd5210SJason Evans {NAME("mapped"), CTL(stats_mapped)},
5881f0a49e8SJason Evans {NAME("retained"), CTL(stats_retained)},
589b7eaed25SJason Evans {NAME("background_thread"),
590b7eaed25SJason Evans CHILD(named, stats_background_thread)},
591b7eaed25SJason Evans {NAME("mutexes"), CHILD(named, stats_mutexes)},
592e722f8f8SJason Evans {NAME("arenas"), CHILD(indexed, stats_arenas)}
593a4bd5210SJason Evans };
594a4bd5210SJason Evans
595*c5ad8142SEric van Gyzen static const ctl_named_node_t experimental_hooks_node[] = {
596*c5ad8142SEric van Gyzen {NAME("install"), CTL(experimental_hooks_install)},
597*c5ad8142SEric van Gyzen {NAME("remove"), CTL(experimental_hooks_remove)}
598*c5ad8142SEric van Gyzen };
599*c5ad8142SEric van Gyzen
600*c5ad8142SEric van Gyzen static const ctl_named_node_t experimental_utilization_node[] = {
601*c5ad8142SEric van Gyzen {NAME("query"), CTL(experimental_utilization_query)},
602*c5ad8142SEric van Gyzen {NAME("batch_query"), CTL(experimental_utilization_batch_query)}
603*c5ad8142SEric van Gyzen };
604*c5ad8142SEric van Gyzen
605*c5ad8142SEric van Gyzen static const ctl_named_node_t experimental_arenas_i_node[] = {
606*c5ad8142SEric van Gyzen {NAME("pactivep"), CTL(experimental_arenas_i_pactivep)}
607*c5ad8142SEric van Gyzen };
608*c5ad8142SEric van Gyzen static const ctl_named_node_t super_experimental_arenas_i_node[] = {
609*c5ad8142SEric van Gyzen {NAME(""), CHILD(named, experimental_arenas_i)}
610*c5ad8142SEric van Gyzen };
611*c5ad8142SEric van Gyzen
612*c5ad8142SEric van Gyzen static const ctl_indexed_node_t experimental_arenas_node[] = {
613*c5ad8142SEric van Gyzen {INDEX(experimental_arenas_i)}
614*c5ad8142SEric van Gyzen };
615*c5ad8142SEric van Gyzen
616*c5ad8142SEric van Gyzen static const ctl_named_node_t experimental_node[] = {
617*c5ad8142SEric van Gyzen {NAME("hooks"), CHILD(named, experimental_hooks)},
618*c5ad8142SEric van Gyzen {NAME("utilization"), CHILD(named, experimental_utilization)},
619*c5ad8142SEric van Gyzen {NAME("arenas"), CHILD(indexed, experimental_arenas)}
620*c5ad8142SEric van Gyzen };
621*c5ad8142SEric van Gyzen
622e722f8f8SJason Evans static const ctl_named_node_t root_node[] = {
623a4bd5210SJason Evans {NAME("version"), CTL(version)},
624a4bd5210SJason Evans {NAME("epoch"), CTL(epoch)},
625b7eaed25SJason Evans {NAME("background_thread"), CTL(background_thread)},
6260ef50b4eSJason Evans {NAME("max_background_threads"), CTL(max_background_threads)},
627e722f8f8SJason Evans {NAME("thread"), CHILD(named, thread)},
628e722f8f8SJason Evans {NAME("config"), CHILD(named, config)},
629e722f8f8SJason Evans {NAME("opt"), CHILD(named, opt)},
630d0e79aa3SJason Evans {NAME("tcache"), CHILD(named, tcache)},
63182872ac0SJason Evans {NAME("arena"), CHILD(indexed, arena)},
632e722f8f8SJason Evans {NAME("arenas"), CHILD(named, arenas)},
633e722f8f8SJason Evans {NAME("prof"), CHILD(named, prof)},
634*c5ad8142SEric van Gyzen {NAME("stats"), CHILD(named, stats)},
635*c5ad8142SEric van Gyzen {NAME("experimental"), CHILD(named, experimental)}
636a4bd5210SJason Evans };
637e722f8f8SJason Evans static const ctl_named_node_t super_root_node[] = {
638e722f8f8SJason Evans {NAME(""), CHILD(named, root)}
639a4bd5210SJason Evans };
640a4bd5210SJason Evans
641a4bd5210SJason Evans #undef NAME
642a4bd5210SJason Evans #undef CHILD
643a4bd5210SJason Evans #undef CTL
644a4bd5210SJason Evans #undef INDEX
645a4bd5210SJason Evans
646a4bd5210SJason Evans /******************************************************************************/
647a4bd5210SJason Evans
648b7eaed25SJason Evans /*
649b7eaed25SJason Evans * Sets *dst + *src non-atomically. This is safe, since everything is
650b7eaed25SJason Evans * synchronized by the ctl mutex.
651b7eaed25SJason Evans */
652a4bd5210SJason Evans static void
ctl_accum_arena_stats_u64(arena_stats_u64_t * dst,arena_stats_u64_t * src)6530ef50b4eSJason Evans ctl_accum_arena_stats_u64(arena_stats_u64_t *dst, arena_stats_u64_t *src) {
654b7eaed25SJason Evans #ifdef JEMALLOC_ATOMIC_U64
655b7eaed25SJason Evans uint64_t cur_dst = atomic_load_u64(dst, ATOMIC_RELAXED);
656b7eaed25SJason Evans uint64_t cur_src = atomic_load_u64(src, ATOMIC_RELAXED);
657b7eaed25SJason Evans atomic_store_u64(dst, cur_dst + cur_src, ATOMIC_RELAXED);
658b7eaed25SJason Evans #else
659b7eaed25SJason Evans *dst += *src;
660b7eaed25SJason Evans #endif
661b7eaed25SJason Evans }
662a4bd5210SJason Evans
663b7eaed25SJason Evans /* Likewise: with ctl mutex synchronization, reading is simple. */
664b7eaed25SJason Evans static uint64_t
ctl_arena_stats_read_u64(arena_stats_u64_t * p)6650ef50b4eSJason Evans ctl_arena_stats_read_u64(arena_stats_u64_t *p) {
666b7eaed25SJason Evans #ifdef JEMALLOC_ATOMIC_U64
667b7eaed25SJason Evans return atomic_load_u64(p, ATOMIC_RELAXED);
668b7eaed25SJason Evans #else
669b7eaed25SJason Evans return *p;
670b7eaed25SJason Evans #endif
671b7eaed25SJason Evans }
672b7eaed25SJason Evans
6730ef50b4eSJason Evans static void
accum_atomic_zu(atomic_zu_t * dst,atomic_zu_t * src)6740ef50b4eSJason Evans accum_atomic_zu(atomic_zu_t *dst, atomic_zu_t *src) {
675b7eaed25SJason Evans size_t cur_dst = atomic_load_zu(dst, ATOMIC_RELAXED);
676b7eaed25SJason Evans size_t cur_src = atomic_load_zu(src, ATOMIC_RELAXED);
677b7eaed25SJason Evans atomic_store_zu(dst, cur_dst + cur_src, ATOMIC_RELAXED);
678b7eaed25SJason Evans }
679b7eaed25SJason Evans
680b7eaed25SJason Evans /******************************************************************************/
681b7eaed25SJason Evans
682b7eaed25SJason Evans static unsigned
arenas_i2a_impl(size_t i,bool compat,bool validate)683b7eaed25SJason Evans arenas_i2a_impl(size_t i, bool compat, bool validate) {
684b7eaed25SJason Evans unsigned a;
685b7eaed25SJason Evans
686b7eaed25SJason Evans switch (i) {
687b7eaed25SJason Evans case MALLCTL_ARENAS_ALL:
688b7eaed25SJason Evans a = 0;
689b7eaed25SJason Evans break;
690b7eaed25SJason Evans case MALLCTL_ARENAS_DESTROYED:
691b7eaed25SJason Evans a = 1;
692b7eaed25SJason Evans break;
693b7eaed25SJason Evans default:
694b7eaed25SJason Evans if (compat && i == ctl_arenas->narenas) {
695b7eaed25SJason Evans /*
696b7eaed25SJason Evans * Provide deprecated backward compatibility for
697b7eaed25SJason Evans * accessing the merged stats at index narenas rather
698b7eaed25SJason Evans * than via MALLCTL_ARENAS_ALL. This is scheduled for
699b7eaed25SJason Evans * removal in 6.0.0.
700b7eaed25SJason Evans */
701b7eaed25SJason Evans a = 0;
702b7eaed25SJason Evans } else if (validate && i >= ctl_arenas->narenas) {
703b7eaed25SJason Evans a = UINT_MAX;
704b7eaed25SJason Evans } else {
705b7eaed25SJason Evans /*
706b7eaed25SJason Evans * This function should never be called for an index
707b7eaed25SJason Evans * more than one past the range of indices that have
708b7eaed25SJason Evans * initialized ctl data.
709b7eaed25SJason Evans */
710b7eaed25SJason Evans assert(i < ctl_arenas->narenas || (!validate && i ==
711b7eaed25SJason Evans ctl_arenas->narenas));
712b7eaed25SJason Evans a = (unsigned)i + 2;
713b7eaed25SJason Evans }
714b7eaed25SJason Evans break;
715b7eaed25SJason Evans }
716b7eaed25SJason Evans
717b7eaed25SJason Evans return a;
718b7eaed25SJason Evans }
719b7eaed25SJason Evans
720b7eaed25SJason Evans static unsigned
arenas_i2a(size_t i)721b7eaed25SJason Evans arenas_i2a(size_t i) {
722b7eaed25SJason Evans return arenas_i2a_impl(i, true, false);
723b7eaed25SJason Evans }
724b7eaed25SJason Evans
725b7eaed25SJason Evans static ctl_arena_t *
arenas_i_impl(tsd_t * tsd,size_t i,bool compat,bool init)7268b2f5aafSJason Evans arenas_i_impl(tsd_t *tsd, size_t i, bool compat, bool init) {
727b7eaed25SJason Evans ctl_arena_t *ret;
728b7eaed25SJason Evans
729b7eaed25SJason Evans assert(!compat || !init);
730b7eaed25SJason Evans
731b7eaed25SJason Evans ret = ctl_arenas->arenas[arenas_i2a_impl(i, compat, false)];
732b7eaed25SJason Evans if (init && ret == NULL) {
733a4bd5210SJason Evans if (config_stats) {
734b7eaed25SJason Evans struct container_s {
735b7eaed25SJason Evans ctl_arena_t ctl_arena;
736b7eaed25SJason Evans ctl_arena_stats_t astats;
737b7eaed25SJason Evans };
738b7eaed25SJason Evans struct container_s *cont =
7398b2f5aafSJason Evans (struct container_s *)base_alloc(tsd_tsdn(tsd),
7408b2f5aafSJason Evans b0get(), sizeof(struct container_s), QUANTUM);
741b7eaed25SJason Evans if (cont == NULL) {
742b7eaed25SJason Evans return NULL;
743b7eaed25SJason Evans }
744b7eaed25SJason Evans ret = &cont->ctl_arena;
745b7eaed25SJason Evans ret->astats = &cont->astats;
746b7eaed25SJason Evans } else {
7478b2f5aafSJason Evans ret = (ctl_arena_t *)base_alloc(tsd_tsdn(tsd), b0get(),
748b7eaed25SJason Evans sizeof(ctl_arena_t), QUANTUM);
749b7eaed25SJason Evans if (ret == NULL) {
750b7eaed25SJason Evans return NULL;
751b7eaed25SJason Evans }
752b7eaed25SJason Evans }
753b7eaed25SJason Evans ret->arena_ind = (unsigned)i;
754b7eaed25SJason Evans ctl_arenas->arenas[arenas_i2a_impl(i, compat, false)] = ret;
755b7eaed25SJason Evans }
756b7eaed25SJason Evans
757b7eaed25SJason Evans assert(ret == NULL || arenas_i2a(ret->arena_ind) == arenas_i2a(i));
758b7eaed25SJason Evans return ret;
759b7eaed25SJason Evans }
760b7eaed25SJason Evans
761b7eaed25SJason Evans static ctl_arena_t *
arenas_i(size_t i)762b7eaed25SJason Evans arenas_i(size_t i) {
7638b2f5aafSJason Evans ctl_arena_t *ret = arenas_i_impl(tsd_fetch(), i, true, false);
764b7eaed25SJason Evans assert(ret != NULL);
765b7eaed25SJason Evans return ret;
766b7eaed25SJason Evans }
767b7eaed25SJason Evans
768b7eaed25SJason Evans static void
ctl_arena_clear(ctl_arena_t * ctl_arena)769b7eaed25SJason Evans ctl_arena_clear(ctl_arena_t *ctl_arena) {
770b7eaed25SJason Evans ctl_arena->nthreads = 0;
771b7eaed25SJason Evans ctl_arena->dss = dss_prec_names[dss_prec_limit];
772b7eaed25SJason Evans ctl_arena->dirty_decay_ms = -1;
773b7eaed25SJason Evans ctl_arena->muzzy_decay_ms = -1;
774b7eaed25SJason Evans ctl_arena->pactive = 0;
775b7eaed25SJason Evans ctl_arena->pdirty = 0;
776b7eaed25SJason Evans ctl_arena->pmuzzy = 0;
777b7eaed25SJason Evans if (config_stats) {
778b7eaed25SJason Evans memset(&ctl_arena->astats->astats, 0, sizeof(arena_stats_t));
779b7eaed25SJason Evans ctl_arena->astats->allocated_small = 0;
780b7eaed25SJason Evans ctl_arena->astats->nmalloc_small = 0;
781b7eaed25SJason Evans ctl_arena->astats->ndalloc_small = 0;
782b7eaed25SJason Evans ctl_arena->astats->nrequests_small = 0;
783*c5ad8142SEric van Gyzen ctl_arena->astats->nfills_small = 0;
784*c5ad8142SEric van Gyzen ctl_arena->astats->nflushes_small = 0;
785*c5ad8142SEric van Gyzen memset(ctl_arena->astats->bstats, 0, SC_NBINS *
7860ef50b4eSJason Evans sizeof(bin_stats_t));
787*c5ad8142SEric van Gyzen memset(ctl_arena->astats->lstats, 0, (SC_NSIZES - SC_NBINS) *
7880ef50b4eSJason Evans sizeof(arena_stats_large_t));
789*c5ad8142SEric van Gyzen memset(ctl_arena->astats->estats, 0, SC_NPSIZES *
790*c5ad8142SEric van Gyzen sizeof(arena_stats_extents_t));
791a4bd5210SJason Evans }
792a4bd5210SJason Evans }
793a4bd5210SJason Evans
794a4bd5210SJason Evans static void
ctl_arena_stats_amerge(tsdn_t * tsdn,ctl_arena_t * ctl_arena,arena_t * arena)795b7eaed25SJason Evans ctl_arena_stats_amerge(tsdn_t *tsdn, ctl_arena_t *ctl_arena, arena_t *arena) {
796a4bd5210SJason Evans unsigned i;
797a4bd5210SJason Evans
798df0d881dSJason Evans if (config_stats) {
799b7eaed25SJason Evans arena_stats_merge(tsdn, arena, &ctl_arena->nthreads,
800b7eaed25SJason Evans &ctl_arena->dss, &ctl_arena->dirty_decay_ms,
801b7eaed25SJason Evans &ctl_arena->muzzy_decay_ms, &ctl_arena->pactive,
802b7eaed25SJason Evans &ctl_arena->pdirty, &ctl_arena->pmuzzy,
803b7eaed25SJason Evans &ctl_arena->astats->astats, ctl_arena->astats->bstats,
804*c5ad8142SEric van Gyzen ctl_arena->astats->lstats, ctl_arena->astats->estats);
805a4bd5210SJason Evans
806*c5ad8142SEric van Gyzen for (i = 0; i < SC_NBINS; i++) {
807b7eaed25SJason Evans ctl_arena->astats->allocated_small +=
808b7eaed25SJason Evans ctl_arena->astats->bstats[i].curregs *
809b7eaed25SJason Evans sz_index2size(i);
810b7eaed25SJason Evans ctl_arena->astats->nmalloc_small +=
811b7eaed25SJason Evans ctl_arena->astats->bstats[i].nmalloc;
812b7eaed25SJason Evans ctl_arena->astats->ndalloc_small +=
813b7eaed25SJason Evans ctl_arena->astats->bstats[i].ndalloc;
814b7eaed25SJason Evans ctl_arena->astats->nrequests_small +=
815b7eaed25SJason Evans ctl_arena->astats->bstats[i].nrequests;
816*c5ad8142SEric van Gyzen ctl_arena->astats->nfills_small +=
817*c5ad8142SEric van Gyzen ctl_arena->astats->bstats[i].nfills;
818*c5ad8142SEric van Gyzen ctl_arena->astats->nflushes_small +=
819*c5ad8142SEric van Gyzen ctl_arena->astats->bstats[i].nflushes;
820a4bd5210SJason Evans }
821df0d881dSJason Evans } else {
822b7eaed25SJason Evans arena_basic_stats_merge(tsdn, arena, &ctl_arena->nthreads,
823b7eaed25SJason Evans &ctl_arena->dss, &ctl_arena->dirty_decay_ms,
824b7eaed25SJason Evans &ctl_arena->muzzy_decay_ms, &ctl_arena->pactive,
825b7eaed25SJason Evans &ctl_arena->pdirty, &ctl_arena->pmuzzy);
826df0d881dSJason Evans }
827a4bd5210SJason Evans }
828a4bd5210SJason Evans
829a4bd5210SJason Evans static void
ctl_arena_stats_sdmerge(ctl_arena_t * ctl_sdarena,ctl_arena_t * ctl_arena,bool destroyed)830b7eaed25SJason Evans ctl_arena_stats_sdmerge(ctl_arena_t *ctl_sdarena, ctl_arena_t *ctl_arena,
831b7eaed25SJason Evans bool destroyed) {
832a4bd5210SJason Evans unsigned i;
833a4bd5210SJason Evans
834b7eaed25SJason Evans if (!destroyed) {
835b7eaed25SJason Evans ctl_sdarena->nthreads += ctl_arena->nthreads;
836b7eaed25SJason Evans ctl_sdarena->pactive += ctl_arena->pactive;
837b7eaed25SJason Evans ctl_sdarena->pdirty += ctl_arena->pdirty;
838b7eaed25SJason Evans ctl_sdarena->pmuzzy += ctl_arena->pmuzzy;
839b7eaed25SJason Evans } else {
840b7eaed25SJason Evans assert(ctl_arena->nthreads == 0);
841b7eaed25SJason Evans assert(ctl_arena->pactive == 0);
842b7eaed25SJason Evans assert(ctl_arena->pdirty == 0);
843b7eaed25SJason Evans assert(ctl_arena->pmuzzy == 0);
844b7eaed25SJason Evans }
845a4bd5210SJason Evans
846df0d881dSJason Evans if (config_stats) {
847b7eaed25SJason Evans ctl_arena_stats_t *sdstats = ctl_sdarena->astats;
848b7eaed25SJason Evans ctl_arena_stats_t *astats = ctl_arena->astats;
849a4bd5210SJason Evans
850b7eaed25SJason Evans if (!destroyed) {
851b7eaed25SJason Evans accum_atomic_zu(&sdstats->astats.mapped,
852b7eaed25SJason Evans &astats->astats.mapped);
853b7eaed25SJason Evans accum_atomic_zu(&sdstats->astats.retained,
854b7eaed25SJason Evans &astats->astats.retained);
855*c5ad8142SEric van Gyzen accum_atomic_zu(&sdstats->astats.extent_avail,
856*c5ad8142SEric van Gyzen &astats->astats.extent_avail);
857b7eaed25SJason Evans }
858d0e79aa3SJason Evans
8590ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.decay_dirty.npurge,
860b7eaed25SJason Evans &astats->astats.decay_dirty.npurge);
8610ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.decay_dirty.nmadvise,
862b7eaed25SJason Evans &astats->astats.decay_dirty.nmadvise);
8630ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.decay_dirty.purged,
864b7eaed25SJason Evans &astats->astats.decay_dirty.purged);
865a4bd5210SJason Evans
8660ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.decay_muzzy.npurge,
867b7eaed25SJason Evans &astats->astats.decay_muzzy.npurge);
8680ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.decay_muzzy.nmadvise,
869b7eaed25SJason Evans &astats->astats.decay_muzzy.nmadvise);
8700ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.decay_muzzy.purged,
871b7eaed25SJason Evans &astats->astats.decay_muzzy.purged);
872a4bd5210SJason Evans
873b7eaed25SJason Evans #define OP(mtx) malloc_mutex_prof_merge( \
874b7eaed25SJason Evans &(sdstats->astats.mutex_prof_data[ \
875b7eaed25SJason Evans arena_prof_mutex_##mtx]), \
876b7eaed25SJason Evans &(astats->astats.mutex_prof_data[ \
877b7eaed25SJason Evans arena_prof_mutex_##mtx]));
878b7eaed25SJason Evans MUTEX_PROF_ARENA_MUTEXES
879b7eaed25SJason Evans #undef OP
880b7eaed25SJason Evans if (!destroyed) {
881b7eaed25SJason Evans accum_atomic_zu(&sdstats->astats.base,
882b7eaed25SJason Evans &astats->astats.base);
883b7eaed25SJason Evans accum_atomic_zu(&sdstats->astats.internal,
884b7eaed25SJason Evans &astats->astats.internal);
885b7eaed25SJason Evans accum_atomic_zu(&sdstats->astats.resident,
886b7eaed25SJason Evans &astats->astats.resident);
8870ef50b4eSJason Evans accum_atomic_zu(&sdstats->astats.metadata_thp,
8880ef50b4eSJason Evans &astats->astats.metadata_thp);
889b7eaed25SJason Evans } else {
890b7eaed25SJason Evans assert(atomic_load_zu(
891b7eaed25SJason Evans &astats->astats.internal, ATOMIC_RELAXED) == 0);
892b7eaed25SJason Evans }
893b7eaed25SJason Evans
894b7eaed25SJason Evans if (!destroyed) {
895b7eaed25SJason Evans sdstats->allocated_small += astats->allocated_small;
896b7eaed25SJason Evans } else {
897b7eaed25SJason Evans assert(astats->allocated_small == 0);
898b7eaed25SJason Evans }
899b7eaed25SJason Evans sdstats->nmalloc_small += astats->nmalloc_small;
900b7eaed25SJason Evans sdstats->ndalloc_small += astats->ndalloc_small;
901b7eaed25SJason Evans sdstats->nrequests_small += astats->nrequests_small;
902*c5ad8142SEric van Gyzen sdstats->nfills_small += astats->nfills_small;
903*c5ad8142SEric van Gyzen sdstats->nflushes_small += astats->nflushes_small;
904b7eaed25SJason Evans
905b7eaed25SJason Evans if (!destroyed) {
906b7eaed25SJason Evans accum_atomic_zu(&sdstats->astats.allocated_large,
907b7eaed25SJason Evans &astats->astats.allocated_large);
908b7eaed25SJason Evans } else {
909b7eaed25SJason Evans assert(atomic_load_zu(&astats->astats.allocated_large,
910b7eaed25SJason Evans ATOMIC_RELAXED) == 0);
911b7eaed25SJason Evans }
9120ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.nmalloc_large,
913b7eaed25SJason Evans &astats->astats.nmalloc_large);
9140ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.ndalloc_large,
915b7eaed25SJason Evans &astats->astats.ndalloc_large);
9160ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->astats.nrequests_large,
917b7eaed25SJason Evans &astats->astats.nrequests_large);
918*c5ad8142SEric van Gyzen accum_atomic_zu(&sdstats->astats.abandoned_vm,
919*c5ad8142SEric van Gyzen &astats->astats.abandoned_vm);
920b7eaed25SJason Evans
921b7eaed25SJason Evans accum_atomic_zu(&sdstats->astats.tcache_bytes,
922b7eaed25SJason Evans &astats->astats.tcache_bytes);
923b7eaed25SJason Evans
924b7eaed25SJason Evans if (ctl_arena->arena_ind == 0) {
925b7eaed25SJason Evans sdstats->astats.uptime = astats->astats.uptime;
926b7eaed25SJason Evans }
927a4bd5210SJason Evans
928*c5ad8142SEric van Gyzen /* Merge bin stats. */
929*c5ad8142SEric van Gyzen for (i = 0; i < SC_NBINS; i++) {
930b7eaed25SJason Evans sdstats->bstats[i].nmalloc += astats->bstats[i].nmalloc;
931b7eaed25SJason Evans sdstats->bstats[i].ndalloc += astats->bstats[i].ndalloc;
932b7eaed25SJason Evans sdstats->bstats[i].nrequests +=
933df0d881dSJason Evans astats->bstats[i].nrequests;
934b7eaed25SJason Evans if (!destroyed) {
935b7eaed25SJason Evans sdstats->bstats[i].curregs +=
936b7eaed25SJason Evans astats->bstats[i].curregs;
937b7eaed25SJason Evans } else {
938b7eaed25SJason Evans assert(astats->bstats[i].curregs == 0);
939b7eaed25SJason Evans }
940b7eaed25SJason Evans sdstats->bstats[i].nfills += astats->bstats[i].nfills;
941b7eaed25SJason Evans sdstats->bstats[i].nflushes +=
942a4bd5210SJason Evans astats->bstats[i].nflushes;
943b7eaed25SJason Evans sdstats->bstats[i].nslabs += astats->bstats[i].nslabs;
944b7eaed25SJason Evans sdstats->bstats[i].reslabs += astats->bstats[i].reslabs;
945b7eaed25SJason Evans if (!destroyed) {
946b7eaed25SJason Evans sdstats->bstats[i].curslabs +=
947b7eaed25SJason Evans astats->bstats[i].curslabs;
948*c5ad8142SEric van Gyzen sdstats->bstats[i].nonfull_slabs +=
949*c5ad8142SEric van Gyzen astats->bstats[i].nonfull_slabs;
950b7eaed25SJason Evans } else {
951b7eaed25SJason Evans assert(astats->bstats[i].curslabs == 0);
952*c5ad8142SEric van Gyzen assert(astats->bstats[i].nonfull_slabs == 0);
953a4bd5210SJason Evans }
954b7eaed25SJason Evans malloc_mutex_prof_merge(&sdstats->bstats[i].mutex_data,
955b7eaed25SJason Evans &astats->bstats[i].mutex_data);
956a4bd5210SJason Evans }
957d0e79aa3SJason Evans
958*c5ad8142SEric van Gyzen /* Merge stats for large allocations. */
959*c5ad8142SEric van Gyzen for (i = 0; i < SC_NSIZES - SC_NBINS; i++) {
9600ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->lstats[i].nmalloc,
961b7eaed25SJason Evans &astats->lstats[i].nmalloc);
9620ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->lstats[i].ndalloc,
963b7eaed25SJason Evans &astats->lstats[i].ndalloc);
9640ef50b4eSJason Evans ctl_accum_arena_stats_u64(&sdstats->lstats[i].nrequests,
965b7eaed25SJason Evans &astats->lstats[i].nrequests);
966b7eaed25SJason Evans if (!destroyed) {
967b7eaed25SJason Evans sdstats->lstats[i].curlextents +=
968b7eaed25SJason Evans astats->lstats[i].curlextents;
969b7eaed25SJason Evans } else {
970b7eaed25SJason Evans assert(astats->lstats[i].curlextents == 0);
971d0e79aa3SJason Evans }
972df0d881dSJason Evans }
973*c5ad8142SEric van Gyzen
974*c5ad8142SEric van Gyzen /* Merge extents stats. */
975*c5ad8142SEric van Gyzen for (i = 0; i < SC_NPSIZES; i++) {
976*c5ad8142SEric van Gyzen accum_atomic_zu(&sdstats->estats[i].ndirty,
977*c5ad8142SEric van Gyzen &astats->estats[i].ndirty);
978*c5ad8142SEric van Gyzen accum_atomic_zu(&sdstats->estats[i].nmuzzy,
979*c5ad8142SEric van Gyzen &astats->estats[i].nmuzzy);
980*c5ad8142SEric van Gyzen accum_atomic_zu(&sdstats->estats[i].nretained,
981*c5ad8142SEric van Gyzen &astats->estats[i].nretained);
982*c5ad8142SEric van Gyzen accum_atomic_zu(&sdstats->estats[i].dirty_bytes,
983*c5ad8142SEric van Gyzen &astats->estats[i].dirty_bytes);
984*c5ad8142SEric van Gyzen accum_atomic_zu(&sdstats->estats[i].muzzy_bytes,
985*c5ad8142SEric van Gyzen &astats->estats[i].muzzy_bytes);
986*c5ad8142SEric van Gyzen accum_atomic_zu(&sdstats->estats[i].retained_bytes,
987*c5ad8142SEric van Gyzen &astats->estats[i].retained_bytes);
988*c5ad8142SEric van Gyzen }
989d0e79aa3SJason Evans }
990a4bd5210SJason Evans }
991a4bd5210SJason Evans
992a4bd5210SJason Evans static void
ctl_arena_refresh(tsdn_t * tsdn,arena_t * arena,ctl_arena_t * ctl_sdarena,unsigned i,bool destroyed)993b7eaed25SJason Evans ctl_arena_refresh(tsdn_t *tsdn, arena_t *arena, ctl_arena_t *ctl_sdarena,
994b7eaed25SJason Evans unsigned i, bool destroyed) {
995b7eaed25SJason Evans ctl_arena_t *ctl_arena = arenas_i(i);
996a4bd5210SJason Evans
997b7eaed25SJason Evans ctl_arena_clear(ctl_arena);
998b7eaed25SJason Evans ctl_arena_stats_amerge(tsdn, ctl_arena, arena);
999a4bd5210SJason Evans /* Merge into sum stats as well. */
1000b7eaed25SJason Evans ctl_arena_stats_sdmerge(ctl_sdarena, ctl_arena, destroyed);
1001a4bd5210SJason Evans }
1002a4bd5210SJason Evans
1003b7eaed25SJason Evans static unsigned
ctl_arena_init(tsd_t * tsd,extent_hooks_t * extent_hooks)10048b2f5aafSJason Evans ctl_arena_init(tsd_t *tsd, extent_hooks_t *extent_hooks) {
1005b7eaed25SJason Evans unsigned arena_ind;
1006b7eaed25SJason Evans ctl_arena_t *ctl_arena;
1007b7eaed25SJason Evans
1008b7eaed25SJason Evans if ((ctl_arena = ql_last(&ctl_arenas->destroyed, destroyed_link)) !=
1009b7eaed25SJason Evans NULL) {
1010b7eaed25SJason Evans ql_remove(&ctl_arenas->destroyed, ctl_arena, destroyed_link);
1011b7eaed25SJason Evans arena_ind = ctl_arena->arena_ind;
1012b7eaed25SJason Evans } else {
1013b7eaed25SJason Evans arena_ind = ctl_arenas->narenas;
1014b7eaed25SJason Evans }
1015b7eaed25SJason Evans
1016b7eaed25SJason Evans /* Trigger stats allocation. */
10178b2f5aafSJason Evans if (arenas_i_impl(tsd, arena_ind, false, true) == NULL) {
1018b7eaed25SJason Evans return UINT_MAX;
1019b7eaed25SJason Evans }
102082872ac0SJason Evans
1021d0e79aa3SJason Evans /* Initialize new arena. */
10228b2f5aafSJason Evans if (arena_init(tsd_tsdn(tsd), arena_ind, extent_hooks) == NULL) {
1023b7eaed25SJason Evans return UINT_MAX;
102482872ac0SJason Evans }
102582872ac0SJason Evans
1026b7eaed25SJason Evans if (arena_ind == ctl_arenas->narenas) {
1027b7eaed25SJason Evans ctl_arenas->narenas++;
1028b7eaed25SJason Evans }
1029b7eaed25SJason Evans
1030b7eaed25SJason Evans return arena_ind;
103182872ac0SJason Evans }
103282872ac0SJason Evans
1033a4bd5210SJason Evans static void
ctl_background_thread_stats_read(tsdn_t * tsdn)1034b7eaed25SJason Evans ctl_background_thread_stats_read(tsdn_t *tsdn) {
1035b7eaed25SJason Evans background_thread_stats_t *stats = &ctl_stats->background_thread;
1036b7eaed25SJason Evans if (!have_background_thread ||
1037b7eaed25SJason Evans background_thread_stats_read(tsdn, stats)) {
1038b7eaed25SJason Evans memset(stats, 0, sizeof(background_thread_stats_t));
1039b7eaed25SJason Evans nstime_init(&stats->run_interval, 0);
1040b7eaed25SJason Evans }
1041b7eaed25SJason Evans }
1042b7eaed25SJason Evans
1043b7eaed25SJason Evans static void
ctl_refresh(tsdn_t * tsdn)1044b7eaed25SJason Evans ctl_refresh(tsdn_t *tsdn) {
1045a4bd5210SJason Evans unsigned i;
1046b7eaed25SJason Evans ctl_arena_t *ctl_sarena = arenas_i(MALLCTL_ARENAS_ALL);
1047b7eaed25SJason Evans VARIABLE_ARRAY(arena_t *, tarenas, ctl_arenas->narenas);
1048a4bd5210SJason Evans
1049a4bd5210SJason Evans /*
1050a4bd5210SJason Evans * Clear sum stats, since they will be merged into by
1051a4bd5210SJason Evans * ctl_arena_refresh().
1052a4bd5210SJason Evans */
1053b7eaed25SJason Evans ctl_arena_clear(ctl_sarena);
1054a4bd5210SJason Evans
1055b7eaed25SJason Evans for (i = 0; i < ctl_arenas->narenas; i++) {
10561f0a49e8SJason Evans tarenas[i] = arena_get(tsdn, i, false);
1057b7eaed25SJason Evans }
1058d0e79aa3SJason Evans
1059b7eaed25SJason Evans for (i = 0; i < ctl_arenas->narenas; i++) {
1060b7eaed25SJason Evans ctl_arena_t *ctl_arena = arenas_i(i);
1061a4bd5210SJason Evans bool initialized = (tarenas[i] != NULL);
1062a4bd5210SJason Evans
1063b7eaed25SJason Evans ctl_arena->initialized = initialized;
1064b7eaed25SJason Evans if (initialized) {
1065b7eaed25SJason Evans ctl_arena_refresh(tsdn, tarenas[i], ctl_sarena, i,
1066b7eaed25SJason Evans false);
1067b7eaed25SJason Evans }
1068a4bd5210SJason Evans }
1069a4bd5210SJason Evans
1070a4bd5210SJason Evans if (config_stats) {
1071b7eaed25SJason Evans ctl_stats->allocated = ctl_sarena->astats->allocated_small +
1072b7eaed25SJason Evans atomic_load_zu(&ctl_sarena->astats->astats.allocated_large,
1073b7eaed25SJason Evans ATOMIC_RELAXED);
1074b7eaed25SJason Evans ctl_stats->active = (ctl_sarena->pactive << LG_PAGE);
1075b7eaed25SJason Evans ctl_stats->metadata = atomic_load_zu(
1076b7eaed25SJason Evans &ctl_sarena->astats->astats.base, ATOMIC_RELAXED) +
1077b7eaed25SJason Evans atomic_load_zu(&ctl_sarena->astats->astats.internal,
1078b7eaed25SJason Evans ATOMIC_RELAXED);
10790ef50b4eSJason Evans ctl_stats->metadata_thp = atomic_load_zu(
10800ef50b4eSJason Evans &ctl_sarena->astats->astats.metadata_thp, ATOMIC_RELAXED);
1081b7eaed25SJason Evans ctl_stats->resident = atomic_load_zu(
1082b7eaed25SJason Evans &ctl_sarena->astats->astats.resident, ATOMIC_RELAXED);
1083b7eaed25SJason Evans ctl_stats->mapped = atomic_load_zu(
1084b7eaed25SJason Evans &ctl_sarena->astats->astats.mapped, ATOMIC_RELAXED);
1085b7eaed25SJason Evans ctl_stats->retained = atomic_load_zu(
1086b7eaed25SJason Evans &ctl_sarena->astats->astats.retained, ATOMIC_RELAXED);
1087a4bd5210SJason Evans
1088b7eaed25SJason Evans ctl_background_thread_stats_read(tsdn);
1089b7eaed25SJason Evans
1090b7eaed25SJason Evans #define READ_GLOBAL_MUTEX_PROF_DATA(i, mtx) \
1091b7eaed25SJason Evans malloc_mutex_lock(tsdn, &mtx); \
1092b7eaed25SJason Evans malloc_mutex_prof_read(tsdn, &ctl_stats->mutex_prof_data[i], &mtx); \
1093b7eaed25SJason Evans malloc_mutex_unlock(tsdn, &mtx);
1094b7eaed25SJason Evans
1095b7eaed25SJason Evans if (config_prof && opt_prof) {
1096b7eaed25SJason Evans READ_GLOBAL_MUTEX_PROF_DATA(global_prof_mutex_prof,
1097b7eaed25SJason Evans bt2gctx_mtx);
1098b7eaed25SJason Evans }
1099b7eaed25SJason Evans if (have_background_thread) {
1100b7eaed25SJason Evans READ_GLOBAL_MUTEX_PROF_DATA(
1101b7eaed25SJason Evans global_prof_mutex_background_thread,
1102b7eaed25SJason Evans background_thread_lock);
1103b7eaed25SJason Evans } else {
1104b7eaed25SJason Evans memset(&ctl_stats->mutex_prof_data[
1105b7eaed25SJason Evans global_prof_mutex_background_thread], 0,
1106b7eaed25SJason Evans sizeof(mutex_prof_data_t));
1107b7eaed25SJason Evans }
1108b7eaed25SJason Evans /* We own ctl mutex already. */
1109b7eaed25SJason Evans malloc_mutex_prof_read(tsdn,
1110b7eaed25SJason Evans &ctl_stats->mutex_prof_data[global_prof_mutex_ctl],
1111b7eaed25SJason Evans &ctl_mtx);
1112b7eaed25SJason Evans #undef READ_GLOBAL_MUTEX_PROF_DATA
1113b7eaed25SJason Evans }
1114b7eaed25SJason Evans ctl_arenas->epoch++;
1115a4bd5210SJason Evans }
1116a4bd5210SJason Evans
1117a4bd5210SJason Evans static bool
ctl_init(tsd_t * tsd)11188b2f5aafSJason Evans ctl_init(tsd_t *tsd) {
1119a4bd5210SJason Evans bool ret;
11208b2f5aafSJason Evans tsdn_t *tsdn = tsd_tsdn(tsd);
1121a4bd5210SJason Evans
11221f0a49e8SJason Evans malloc_mutex_lock(tsdn, &ctl_mtx);
1123d0e79aa3SJason Evans if (!ctl_initialized) {
1124b7eaed25SJason Evans ctl_arena_t *ctl_sarena, *ctl_darena;
1125a4bd5210SJason Evans unsigned i;
1126b7eaed25SJason Evans
1127b7eaed25SJason Evans /*
1128b7eaed25SJason Evans * Allocate demand-zeroed space for pointers to the full
1129b7eaed25SJason Evans * range of supported arena indices.
1130b7eaed25SJason Evans */
1131b7eaed25SJason Evans if (ctl_arenas == NULL) {
1132b7eaed25SJason Evans ctl_arenas = (ctl_arenas_t *)base_alloc(tsdn,
1133b7eaed25SJason Evans b0get(), sizeof(ctl_arenas_t), QUANTUM);
1134b7eaed25SJason Evans if (ctl_arenas == NULL) {
1135a4bd5210SJason Evans ret = true;
1136a4bd5210SJason Evans goto label_return;
1137a4bd5210SJason Evans }
1138a4bd5210SJason Evans }
1139a4bd5210SJason Evans
1140b7eaed25SJason Evans if (config_stats && ctl_stats == NULL) {
1141b7eaed25SJason Evans ctl_stats = (ctl_stats_t *)base_alloc(tsdn, b0get(),
1142b7eaed25SJason Evans sizeof(ctl_stats_t), QUANTUM);
1143b7eaed25SJason Evans if (ctl_stats == NULL) {
1144b7eaed25SJason Evans ret = true;
1145b7eaed25SJason Evans goto label_return;
1146b7eaed25SJason Evans }
1147b7eaed25SJason Evans }
1148b7eaed25SJason Evans
1149b7eaed25SJason Evans /*
1150b7eaed25SJason Evans * Allocate space for the current full range of arenas
1151b7eaed25SJason Evans * here rather than doing it lazily elsewhere, in order
1152b7eaed25SJason Evans * to limit when OOM-caused errors can occur.
1153b7eaed25SJason Evans */
11548b2f5aafSJason Evans if ((ctl_sarena = arenas_i_impl(tsd, MALLCTL_ARENAS_ALL, false,
1155b7eaed25SJason Evans true)) == NULL) {
1156b7eaed25SJason Evans ret = true;
1157b7eaed25SJason Evans goto label_return;
1158b7eaed25SJason Evans }
1159b7eaed25SJason Evans ctl_sarena->initialized = true;
1160b7eaed25SJason Evans
11618b2f5aafSJason Evans if ((ctl_darena = arenas_i_impl(tsd, MALLCTL_ARENAS_DESTROYED,
1162b7eaed25SJason Evans false, true)) == NULL) {
1163b7eaed25SJason Evans ret = true;
1164b7eaed25SJason Evans goto label_return;
1165b7eaed25SJason Evans }
1166b7eaed25SJason Evans ctl_arena_clear(ctl_darena);
1167b7eaed25SJason Evans /*
1168b7eaed25SJason Evans * Don't toggle ctl_darena to initialized until an arena is
1169b7eaed25SJason Evans * actually destroyed, so that arena.<i>.initialized can be used
1170b7eaed25SJason Evans * to query whether the stats are relevant.
1171b7eaed25SJason Evans */
1172b7eaed25SJason Evans
1173b7eaed25SJason Evans ctl_arenas->narenas = narenas_total_get();
1174b7eaed25SJason Evans for (i = 0; i < ctl_arenas->narenas; i++) {
11758b2f5aafSJason Evans if (arenas_i_impl(tsd, i, false, true) == NULL) {
1176b7eaed25SJason Evans ret = true;
1177b7eaed25SJason Evans goto label_return;
1178b7eaed25SJason Evans }
1179b7eaed25SJason Evans }
1180b7eaed25SJason Evans
1181b7eaed25SJason Evans ql_new(&ctl_arenas->destroyed);
11821f0a49e8SJason Evans ctl_refresh(tsdn);
1183b7eaed25SJason Evans
1184a4bd5210SJason Evans ctl_initialized = true;
1185a4bd5210SJason Evans }
1186a4bd5210SJason Evans
1187a4bd5210SJason Evans ret = false;
1188a4bd5210SJason Evans label_return:
11891f0a49e8SJason Evans malloc_mutex_unlock(tsdn, &ctl_mtx);
1190b7eaed25SJason Evans return ret;
1191a4bd5210SJason Evans }
1192a4bd5210SJason Evans
1193a4bd5210SJason Evans static int
ctl_lookup(tsdn_t * tsdn,const char * name,ctl_node_t const ** nodesp,size_t * mibp,size_t * depthp)11941f0a49e8SJason Evans ctl_lookup(tsdn_t *tsdn, const char *name, ctl_node_t const **nodesp,
1195b7eaed25SJason Evans size_t *mibp, size_t *depthp) {
1196a4bd5210SJason Evans int ret;
1197a4bd5210SJason Evans const char *elm, *tdot, *dot;
1198a4bd5210SJason Evans size_t elen, i, j;
1199e722f8f8SJason Evans const ctl_named_node_t *node;
1200a4bd5210SJason Evans
1201a4bd5210SJason Evans elm = name;
1202a4bd5210SJason Evans /* Equivalent to strchrnul(). */
1203a4bd5210SJason Evans dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot : strchr(elm, '\0');
1204a4bd5210SJason Evans elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
1205a4bd5210SJason Evans if (elen == 0) {
1206a4bd5210SJason Evans ret = ENOENT;
1207a4bd5210SJason Evans goto label_return;
1208a4bd5210SJason Evans }
1209a4bd5210SJason Evans node = super_root_node;
1210a4bd5210SJason Evans for (i = 0; i < *depthp; i++) {
1211e722f8f8SJason Evans assert(node);
1212e722f8f8SJason Evans assert(node->nchildren > 0);
1213e722f8f8SJason Evans if (ctl_named_node(node->children) != NULL) {
1214e722f8f8SJason Evans const ctl_named_node_t *pnode = node;
1215a4bd5210SJason Evans
1216a4bd5210SJason Evans /* Children are named. */
1217e722f8f8SJason Evans for (j = 0; j < node->nchildren; j++) {
1218e722f8f8SJason Evans const ctl_named_node_t *child =
1219e722f8f8SJason Evans ctl_named_children(node, j);
1220e722f8f8SJason Evans if (strlen(child->name) == elen &&
1221e722f8f8SJason Evans strncmp(elm, child->name, elen) == 0) {
1222a4bd5210SJason Evans node = child;
1223b7eaed25SJason Evans if (nodesp != NULL) {
1224e722f8f8SJason Evans nodesp[i] =
1225e722f8f8SJason Evans (const ctl_node_t *)node;
1226b7eaed25SJason Evans }
1227a4bd5210SJason Evans mibp[i] = j;
1228a4bd5210SJason Evans break;
1229a4bd5210SJason Evans }
1230a4bd5210SJason Evans }
1231a4bd5210SJason Evans if (node == pnode) {
1232a4bd5210SJason Evans ret = ENOENT;
1233a4bd5210SJason Evans goto label_return;
1234a4bd5210SJason Evans }
1235a4bd5210SJason Evans } else {
1236a4bd5210SJason Evans uintmax_t index;
1237e722f8f8SJason Evans const ctl_indexed_node_t *inode;
1238a4bd5210SJason Evans
1239a4bd5210SJason Evans /* Children are indexed. */
1240a4bd5210SJason Evans index = malloc_strtoumax(elm, NULL, 10);
1241a4bd5210SJason Evans if (index == UINTMAX_MAX || index > SIZE_T_MAX) {
1242a4bd5210SJason Evans ret = ENOENT;
1243a4bd5210SJason Evans goto label_return;
1244a4bd5210SJason Evans }
1245a4bd5210SJason Evans
1246e722f8f8SJason Evans inode = ctl_indexed_node(node->children);
12471f0a49e8SJason Evans node = inode->index(tsdn, mibp, *depthp, (size_t)index);
1248a4bd5210SJason Evans if (node == NULL) {
1249a4bd5210SJason Evans ret = ENOENT;
1250a4bd5210SJason Evans goto label_return;
1251a4bd5210SJason Evans }
1252a4bd5210SJason Evans
1253b7eaed25SJason Evans if (nodesp != NULL) {
1254e722f8f8SJason Evans nodesp[i] = (const ctl_node_t *)node;
1255b7eaed25SJason Evans }
1256a4bd5210SJason Evans mibp[i] = (size_t)index;
1257a4bd5210SJason Evans }
1258a4bd5210SJason Evans
1259a4bd5210SJason Evans if (node->ctl != NULL) {
1260a4bd5210SJason Evans /* Terminal node. */
1261a4bd5210SJason Evans if (*dot != '\0') {
1262a4bd5210SJason Evans /*
1263a4bd5210SJason Evans * The name contains more elements than are
1264a4bd5210SJason Evans * in this path through the tree.
1265a4bd5210SJason Evans */
1266a4bd5210SJason Evans ret = ENOENT;
1267a4bd5210SJason Evans goto label_return;
1268a4bd5210SJason Evans }
1269a4bd5210SJason Evans /* Complete lookup successful. */
1270a4bd5210SJason Evans *depthp = i + 1;
1271a4bd5210SJason Evans break;
1272a4bd5210SJason Evans }
1273a4bd5210SJason Evans
1274a4bd5210SJason Evans /* Update elm. */
1275a4bd5210SJason Evans if (*dot == '\0') {
1276a4bd5210SJason Evans /* No more elements. */
1277a4bd5210SJason Evans ret = ENOENT;
1278a4bd5210SJason Evans goto label_return;
1279a4bd5210SJason Evans }
1280a4bd5210SJason Evans elm = &dot[1];
1281a4bd5210SJason Evans dot = ((tdot = strchr(elm, '.')) != NULL) ? tdot :
1282a4bd5210SJason Evans strchr(elm, '\0');
1283a4bd5210SJason Evans elen = (size_t)((uintptr_t)dot - (uintptr_t)elm);
1284a4bd5210SJason Evans }
1285a4bd5210SJason Evans
1286a4bd5210SJason Evans ret = 0;
1287a4bd5210SJason Evans label_return:
1288b7eaed25SJason Evans return ret;
1289a4bd5210SJason Evans }
1290a4bd5210SJason Evans
1291a4bd5210SJason Evans int
ctl_byname(tsd_t * tsd,const char * name,void * oldp,size_t * oldlenp,void * newp,size_t newlen)12921f0a49e8SJason Evans ctl_byname(tsd_t *tsd, const char *name, void *oldp, size_t *oldlenp,
1293b7eaed25SJason Evans void *newp, size_t newlen) {
1294a4bd5210SJason Evans int ret;
1295a4bd5210SJason Evans size_t depth;
1296a4bd5210SJason Evans ctl_node_t const *nodes[CTL_MAX_DEPTH];
1297a4bd5210SJason Evans size_t mib[CTL_MAX_DEPTH];
1298e722f8f8SJason Evans const ctl_named_node_t *node;
1299a4bd5210SJason Evans
13008b2f5aafSJason Evans if (!ctl_initialized && ctl_init(tsd)) {
1301a4bd5210SJason Evans ret = EAGAIN;
1302a4bd5210SJason Evans goto label_return;
1303a4bd5210SJason Evans }
1304a4bd5210SJason Evans
1305a4bd5210SJason Evans depth = CTL_MAX_DEPTH;
13061f0a49e8SJason Evans ret = ctl_lookup(tsd_tsdn(tsd), name, nodes, mib, &depth);
1307b7eaed25SJason Evans if (ret != 0) {
1308a4bd5210SJason Evans goto label_return;
1309b7eaed25SJason Evans }
1310a4bd5210SJason Evans
1311e722f8f8SJason Evans node = ctl_named_node(nodes[depth-1]);
1312b7eaed25SJason Evans if (node != NULL && node->ctl) {
13131f0a49e8SJason Evans ret = node->ctl(tsd, mib, depth, oldp, oldlenp, newp, newlen);
1314b7eaed25SJason Evans } else {
1315a4bd5210SJason Evans /* The name refers to a partial path through the ctl tree. */
1316a4bd5210SJason Evans ret = ENOENT;
1317a4bd5210SJason Evans }
1318a4bd5210SJason Evans
1319a4bd5210SJason Evans label_return:
1320a4bd5210SJason Evans return(ret);
1321a4bd5210SJason Evans }
1322a4bd5210SJason Evans
1323a4bd5210SJason Evans int
ctl_nametomib(tsd_t * tsd,const char * name,size_t * mibp,size_t * miblenp)13248b2f5aafSJason Evans ctl_nametomib(tsd_t *tsd, const char *name, size_t *mibp, size_t *miblenp) {
1325a4bd5210SJason Evans int ret;
1326a4bd5210SJason Evans
13278b2f5aafSJason Evans if (!ctl_initialized && ctl_init(tsd)) {
1328a4bd5210SJason Evans ret = EAGAIN;
1329a4bd5210SJason Evans goto label_return;
1330a4bd5210SJason Evans }
1331a4bd5210SJason Evans
13328b2f5aafSJason Evans ret = ctl_lookup(tsd_tsdn(tsd), name, NULL, mibp, miblenp);
1333a4bd5210SJason Evans label_return:
1334a4bd5210SJason Evans return(ret);
1335a4bd5210SJason Evans }
1336a4bd5210SJason Evans
1337a4bd5210SJason Evans int
ctl_bymib(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)13381f0a49e8SJason Evans ctl_bymib(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
1339b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) {
1340a4bd5210SJason Evans int ret;
1341e722f8f8SJason Evans const ctl_named_node_t *node;
1342a4bd5210SJason Evans size_t i;
1343a4bd5210SJason Evans
13448b2f5aafSJason Evans if (!ctl_initialized && ctl_init(tsd)) {
1345a4bd5210SJason Evans ret = EAGAIN;
1346a4bd5210SJason Evans goto label_return;
1347a4bd5210SJason Evans }
1348a4bd5210SJason Evans
1349a4bd5210SJason Evans /* Iterate down the tree. */
1350a4bd5210SJason Evans node = super_root_node;
1351a4bd5210SJason Evans for (i = 0; i < miblen; i++) {
1352e722f8f8SJason Evans assert(node);
1353e722f8f8SJason Evans assert(node->nchildren > 0);
1354e722f8f8SJason Evans if (ctl_named_node(node->children) != NULL) {
1355a4bd5210SJason Evans /* Children are named. */
1356b7eaed25SJason Evans if (node->nchildren <= mib[i]) {
1357a4bd5210SJason Evans ret = ENOENT;
1358a4bd5210SJason Evans goto label_return;
1359a4bd5210SJason Evans }
1360e722f8f8SJason Evans node = ctl_named_children(node, mib[i]);
1361a4bd5210SJason Evans } else {
1362e722f8f8SJason Evans const ctl_indexed_node_t *inode;
1363a4bd5210SJason Evans
1364a4bd5210SJason Evans /* Indexed element. */
1365e722f8f8SJason Evans inode = ctl_indexed_node(node->children);
13661f0a49e8SJason Evans node = inode->index(tsd_tsdn(tsd), mib, miblen, mib[i]);
1367a4bd5210SJason Evans if (node == NULL) {
1368a4bd5210SJason Evans ret = ENOENT;
1369a4bd5210SJason Evans goto label_return;
1370a4bd5210SJason Evans }
1371a4bd5210SJason Evans }
1372a4bd5210SJason Evans }
1373a4bd5210SJason Evans
1374a4bd5210SJason Evans /* Call the ctl function. */
1375b7eaed25SJason Evans if (node && node->ctl) {
13761f0a49e8SJason Evans ret = node->ctl(tsd, mib, miblen, oldp, oldlenp, newp, newlen);
1377b7eaed25SJason Evans } else {
1378a4bd5210SJason Evans /* Partial MIB. */
1379a4bd5210SJason Evans ret = ENOENT;
1380a4bd5210SJason Evans }
1381a4bd5210SJason Evans
1382a4bd5210SJason Evans label_return:
1383a4bd5210SJason Evans return(ret);
1384a4bd5210SJason Evans }
1385a4bd5210SJason Evans
1386a4bd5210SJason Evans bool
ctl_boot(void)1387b7eaed25SJason Evans ctl_boot(void) {
1388b7eaed25SJason Evans if (malloc_mutex_init(&ctl_mtx, "ctl", WITNESS_RANK_CTL,
1389b7eaed25SJason Evans malloc_mutex_rank_exclusive)) {
1390b7eaed25SJason Evans return true;
1391b7eaed25SJason Evans }
1392a4bd5210SJason Evans
1393a4bd5210SJason Evans ctl_initialized = false;
1394a4bd5210SJason Evans
1395b7eaed25SJason Evans return false;
1396a4bd5210SJason Evans }
1397a4bd5210SJason Evans
139882872ac0SJason Evans void
ctl_prefork(tsdn_t * tsdn)1399b7eaed25SJason Evans ctl_prefork(tsdn_t *tsdn) {
14001f0a49e8SJason Evans malloc_mutex_prefork(tsdn, &ctl_mtx);
140182872ac0SJason Evans }
140282872ac0SJason Evans
140382872ac0SJason Evans void
ctl_postfork_parent(tsdn_t * tsdn)1404b7eaed25SJason Evans ctl_postfork_parent(tsdn_t *tsdn) {
14051f0a49e8SJason Evans malloc_mutex_postfork_parent(tsdn, &ctl_mtx);
140682872ac0SJason Evans }
140782872ac0SJason Evans
140882872ac0SJason Evans void
ctl_postfork_child(tsdn_t * tsdn)1409b7eaed25SJason Evans ctl_postfork_child(tsdn_t *tsdn) {
14101f0a49e8SJason Evans malloc_mutex_postfork_child(tsdn, &ctl_mtx);
141182872ac0SJason Evans }
141282872ac0SJason Evans
1413a4bd5210SJason Evans /******************************************************************************/
1414a4bd5210SJason Evans /* *_ctl() functions. */
1415a4bd5210SJason Evans
1416a4bd5210SJason Evans #define READONLY() do { \
1417a4bd5210SJason Evans if (newp != NULL || newlen != 0) { \
1418a4bd5210SJason Evans ret = EPERM; \
1419a4bd5210SJason Evans goto label_return; \
1420a4bd5210SJason Evans } \
1421a4bd5210SJason Evans } while (0)
1422a4bd5210SJason Evans
1423a4bd5210SJason Evans #define WRITEONLY() do { \
1424a4bd5210SJason Evans if (oldp != NULL || oldlenp != NULL) { \
1425a4bd5210SJason Evans ret = EPERM; \
1426a4bd5210SJason Evans goto label_return; \
1427a4bd5210SJason Evans } \
1428a4bd5210SJason Evans } while (0)
1429a4bd5210SJason Evans
1430d0e79aa3SJason Evans #define READ_XOR_WRITE() do { \
1431d0e79aa3SJason Evans if ((oldp != NULL && oldlenp != NULL) && (newp != NULL || \
1432d0e79aa3SJason Evans newlen != 0)) { \
1433d0e79aa3SJason Evans ret = EPERM; \
1434d0e79aa3SJason Evans goto label_return; \
1435d0e79aa3SJason Evans } \
1436d0e79aa3SJason Evans } while (0)
1437d0e79aa3SJason Evans
1438a4bd5210SJason Evans #define READ(v, t) do { \
1439a4bd5210SJason Evans if (oldp != NULL && oldlenp != NULL) { \
1440a4bd5210SJason Evans if (*oldlenp != sizeof(t)) { \
1441a4bd5210SJason Evans size_t copylen = (sizeof(t) <= *oldlenp) \
1442a4bd5210SJason Evans ? sizeof(t) : *oldlenp; \
144388ad2f8dSJason Evans memcpy(oldp, (void *)&(v), copylen); \
1444a4bd5210SJason Evans ret = EINVAL; \
1445a4bd5210SJason Evans goto label_return; \
1446d0e79aa3SJason Evans } \
144788ad2f8dSJason Evans *(t *)oldp = (v); \
1448a4bd5210SJason Evans } \
1449a4bd5210SJason Evans } while (0)
1450a4bd5210SJason Evans
1451a4bd5210SJason Evans #define WRITE(v, t) do { \
1452a4bd5210SJason Evans if (newp != NULL) { \
1453a4bd5210SJason Evans if (newlen != sizeof(t)) { \
1454a4bd5210SJason Evans ret = EINVAL; \
1455a4bd5210SJason Evans goto label_return; \
1456a4bd5210SJason Evans } \
145788ad2f8dSJason Evans (v) = *(t *)newp; \
1458a4bd5210SJason Evans } \
1459a4bd5210SJason Evans } while (0)
1460a4bd5210SJason Evans
1461b7eaed25SJason Evans #define MIB_UNSIGNED(v, i) do { \
1462b7eaed25SJason Evans if (mib[i] > UINT_MAX) { \
1463b7eaed25SJason Evans ret = EFAULT; \
1464b7eaed25SJason Evans goto label_return; \
1465b7eaed25SJason Evans } \
1466b7eaed25SJason Evans v = (unsigned)mib[i]; \
1467b7eaed25SJason Evans } while (0)
1468b7eaed25SJason Evans
1469a4bd5210SJason Evans /*
1470a4bd5210SJason Evans * There's a lot of code duplication in the following macros due to limitations
1471a4bd5210SJason Evans * in how nested cpp macros are expanded.
1472a4bd5210SJason Evans */
1473a4bd5210SJason Evans #define CTL_RO_CLGEN(c, l, n, v, t) \
1474a4bd5210SJason Evans static int \
14751f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \
1476b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) { \
1477a4bd5210SJason Evans int ret; \
1478a4bd5210SJason Evans t oldval; \
1479a4bd5210SJason Evans \
1480b7eaed25SJason Evans if (!(c)) { \
1481b7eaed25SJason Evans return ENOENT; \
1482b7eaed25SJason Evans } \
1483b7eaed25SJason Evans if (l) { \
14841f0a49e8SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); \
1485b7eaed25SJason Evans } \
1486a4bd5210SJason Evans READONLY(); \
148788ad2f8dSJason Evans oldval = (v); \
1488a4bd5210SJason Evans READ(oldval, t); \
1489a4bd5210SJason Evans \
1490a4bd5210SJason Evans ret = 0; \
1491a4bd5210SJason Evans label_return: \
1492b7eaed25SJason Evans if (l) { \
14931f0a49e8SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); \
1494b7eaed25SJason Evans } \
1495b7eaed25SJason Evans return ret; \
1496a4bd5210SJason Evans }
1497a4bd5210SJason Evans
1498a4bd5210SJason Evans #define CTL_RO_CGEN(c, n, v, t) \
1499a4bd5210SJason Evans static int \
1500*c5ad8142SEric van Gyzen n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
1501*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
1502a4bd5210SJason Evans int ret; \
1503a4bd5210SJason Evans t oldval; \
1504a4bd5210SJason Evans \
1505b7eaed25SJason Evans if (!(c)) { \
1506b7eaed25SJason Evans return ENOENT; \
1507b7eaed25SJason Evans } \
15081f0a49e8SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); \
1509a4bd5210SJason Evans READONLY(); \
151088ad2f8dSJason Evans oldval = (v); \
1511a4bd5210SJason Evans READ(oldval, t); \
1512a4bd5210SJason Evans \
1513a4bd5210SJason Evans ret = 0; \
1514a4bd5210SJason Evans label_return: \
15151f0a49e8SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); \
1516b7eaed25SJason Evans return ret; \
1517a4bd5210SJason Evans }
1518a4bd5210SJason Evans
1519a4bd5210SJason Evans #define CTL_RO_GEN(n, v, t) \
1520a4bd5210SJason Evans static int \
15211f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \
1522b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) { \
1523a4bd5210SJason Evans int ret; \
1524a4bd5210SJason Evans t oldval; \
1525a4bd5210SJason Evans \
15261f0a49e8SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx); \
1527a4bd5210SJason Evans READONLY(); \
152888ad2f8dSJason Evans oldval = (v); \
1529a4bd5210SJason Evans READ(oldval, t); \
1530a4bd5210SJason Evans \
1531a4bd5210SJason Evans ret = 0; \
1532a4bd5210SJason Evans label_return: \
15331f0a49e8SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx); \
1534b7eaed25SJason Evans return ret; \
1535a4bd5210SJason Evans }
1536a4bd5210SJason Evans
1537a4bd5210SJason Evans /*
1538a4bd5210SJason Evans * ctl_mtx is not acquired, under the assumption that no pertinent data will
1539a4bd5210SJason Evans * mutate during the call.
1540a4bd5210SJason Evans */
1541a4bd5210SJason Evans #define CTL_RO_NL_CGEN(c, n, v, t) \
1542a4bd5210SJason Evans static int \
1543*c5ad8142SEric van Gyzen n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
1544*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
1545a4bd5210SJason Evans int ret; \
1546a4bd5210SJason Evans t oldval; \
1547a4bd5210SJason Evans \
1548b7eaed25SJason Evans if (!(c)) { \
1549b7eaed25SJason Evans return ENOENT; \
1550b7eaed25SJason Evans } \
1551a4bd5210SJason Evans READONLY(); \
155288ad2f8dSJason Evans oldval = (v); \
1553a4bd5210SJason Evans READ(oldval, t); \
1554a4bd5210SJason Evans \
1555a4bd5210SJason Evans ret = 0; \
1556a4bd5210SJason Evans label_return: \
1557b7eaed25SJason Evans return ret; \
1558a4bd5210SJason Evans }
1559a4bd5210SJason Evans
1560a4bd5210SJason Evans #define CTL_RO_NL_GEN(n, v, t) \
1561a4bd5210SJason Evans static int \
1562*c5ad8142SEric van Gyzen n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
1563*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
1564a4bd5210SJason Evans int ret; \
1565a4bd5210SJason Evans t oldval; \
1566a4bd5210SJason Evans \
1567a4bd5210SJason Evans READONLY(); \
156888ad2f8dSJason Evans oldval = (v); \
1569a4bd5210SJason Evans READ(oldval, t); \
1570a4bd5210SJason Evans \
1571a4bd5210SJason Evans ret = 0; \
1572a4bd5210SJason Evans label_return: \
1573b7eaed25SJason Evans return ret; \
1574a4bd5210SJason Evans }
1575a4bd5210SJason Evans
1576d0e79aa3SJason Evans #define CTL_TSD_RO_NL_CGEN(c, n, m, t) \
1577d0e79aa3SJason Evans static int \
15781f0a49e8SJason Evans n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp, \
1579b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) { \
1580d0e79aa3SJason Evans int ret; \
1581d0e79aa3SJason Evans t oldval; \
1582d0e79aa3SJason Evans \
1583b7eaed25SJason Evans if (!(c)) { \
1584b7eaed25SJason Evans return ENOENT; \
1585b7eaed25SJason Evans } \
1586d0e79aa3SJason Evans READONLY(); \
1587d0e79aa3SJason Evans oldval = (m(tsd)); \
1588d0e79aa3SJason Evans READ(oldval, t); \
1589d0e79aa3SJason Evans \
1590d0e79aa3SJason Evans ret = 0; \
1591d0e79aa3SJason Evans label_return: \
1592b7eaed25SJason Evans return ret; \
1593d0e79aa3SJason Evans }
1594d0e79aa3SJason Evans
1595df0d881dSJason Evans #define CTL_RO_CONFIG_GEN(n, t) \
1596a4bd5210SJason Evans static int \
1597*c5ad8142SEric van Gyzen n##_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, \
1598*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) { \
1599a4bd5210SJason Evans int ret; \
1600df0d881dSJason Evans t oldval; \
1601a4bd5210SJason Evans \
1602a4bd5210SJason Evans READONLY(); \
1603a4bd5210SJason Evans oldval = n; \
1604df0d881dSJason Evans READ(oldval, t); \
1605a4bd5210SJason Evans \
1606a4bd5210SJason Evans ret = 0; \
1607a4bd5210SJason Evans label_return: \
1608b7eaed25SJason Evans return ret; \
1609a4bd5210SJason Evans }
1610a4bd5210SJason Evans
1611f921d10fSJason Evans /******************************************************************************/
1612f921d10fSJason Evans
CTL_RO_NL_GEN(version,JEMALLOC_VERSION,const char *)1613a4bd5210SJason Evans CTL_RO_NL_GEN(version, JEMALLOC_VERSION, const char *)
1614a4bd5210SJason Evans
1615a4bd5210SJason Evans static int
1616*c5ad8142SEric van Gyzen epoch_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1617*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
1618a4bd5210SJason Evans int ret;
16192b06b201SJason Evans UNUSED uint64_t newval;
1620a4bd5210SJason Evans
16211f0a49e8SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1622a4bd5210SJason Evans WRITE(newval, uint64_t);
1623b7eaed25SJason Evans if (newp != NULL) {
16241f0a49e8SJason Evans ctl_refresh(tsd_tsdn(tsd));
1625b7eaed25SJason Evans }
1626b7eaed25SJason Evans READ(ctl_arenas->epoch, uint64_t);
1627a4bd5210SJason Evans
1628a4bd5210SJason Evans ret = 0;
1629a4bd5210SJason Evans label_return:
16301f0a49e8SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1631b7eaed25SJason Evans return ret;
1632b7eaed25SJason Evans }
1633b7eaed25SJason Evans
1634b7eaed25SJason Evans static int
background_thread_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1635*c5ad8142SEric van Gyzen background_thread_ctl(tsd_t *tsd, const size_t *mib,
1636*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp,
1637*c5ad8142SEric van Gyzen void *newp, size_t newlen) {
1638b7eaed25SJason Evans int ret;
1639b7eaed25SJason Evans bool oldval;
1640b7eaed25SJason Evans
1641b7eaed25SJason Evans if (!have_background_thread) {
1642b7eaed25SJason Evans return ENOENT;
1643b7eaed25SJason Evans }
1644b7eaed25SJason Evans background_thread_ctl_init(tsd_tsdn(tsd));
1645b7eaed25SJason Evans
1646b7eaed25SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
1647b7eaed25SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
1648b7eaed25SJason Evans if (newp == NULL) {
1649b7eaed25SJason Evans oldval = background_thread_enabled();
1650b7eaed25SJason Evans READ(oldval, bool);
1651b7eaed25SJason Evans } else {
1652b7eaed25SJason Evans if (newlen != sizeof(bool)) {
1653b7eaed25SJason Evans ret = EINVAL;
1654b7eaed25SJason Evans goto label_return;
1655b7eaed25SJason Evans }
1656b7eaed25SJason Evans oldval = background_thread_enabled();
1657b7eaed25SJason Evans READ(oldval, bool);
1658b7eaed25SJason Evans
1659b7eaed25SJason Evans bool newval = *(bool *)newp;
1660b7eaed25SJason Evans if (newval == oldval) {
1661b7eaed25SJason Evans ret = 0;
1662b7eaed25SJason Evans goto label_return;
1663b7eaed25SJason Evans }
1664b7eaed25SJason Evans
1665b7eaed25SJason Evans background_thread_enabled_set(tsd_tsdn(tsd), newval);
1666b7eaed25SJason Evans if (newval) {
1667b7eaed25SJason Evans if (background_threads_enable(tsd)) {
1668b7eaed25SJason Evans ret = EFAULT;
1669b7eaed25SJason Evans goto label_return;
1670b7eaed25SJason Evans }
1671b7eaed25SJason Evans } else {
1672b7eaed25SJason Evans if (background_threads_disable(tsd)) {
1673b7eaed25SJason Evans ret = EFAULT;
1674b7eaed25SJason Evans goto label_return;
1675b7eaed25SJason Evans }
1676b7eaed25SJason Evans }
1677b7eaed25SJason Evans }
1678b7eaed25SJason Evans ret = 0;
1679b7eaed25SJason Evans label_return:
1680b7eaed25SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
1681b7eaed25SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
1682b7eaed25SJason Evans
1683b7eaed25SJason Evans return ret;
1684a4bd5210SJason Evans }
1685a4bd5210SJason Evans
16860ef50b4eSJason Evans static int
max_background_threads_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1687*c5ad8142SEric van Gyzen max_background_threads_ctl(tsd_t *tsd, const size_t *mib,
1688*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
1689*c5ad8142SEric van Gyzen size_t newlen) {
16900ef50b4eSJason Evans int ret;
16910ef50b4eSJason Evans size_t oldval;
16920ef50b4eSJason Evans
16930ef50b4eSJason Evans if (!have_background_thread) {
16940ef50b4eSJason Evans return ENOENT;
16950ef50b4eSJason Evans }
16960ef50b4eSJason Evans background_thread_ctl_init(tsd_tsdn(tsd));
16970ef50b4eSJason Evans
16980ef50b4eSJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
16990ef50b4eSJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
17000ef50b4eSJason Evans if (newp == NULL) {
17010ef50b4eSJason Evans oldval = max_background_threads;
17020ef50b4eSJason Evans READ(oldval, size_t);
17030ef50b4eSJason Evans } else {
17040ef50b4eSJason Evans if (newlen != sizeof(size_t)) {
17050ef50b4eSJason Evans ret = EINVAL;
17060ef50b4eSJason Evans goto label_return;
17070ef50b4eSJason Evans }
17080ef50b4eSJason Evans oldval = max_background_threads;
17090ef50b4eSJason Evans READ(oldval, size_t);
17100ef50b4eSJason Evans
17110ef50b4eSJason Evans size_t newval = *(size_t *)newp;
17120ef50b4eSJason Evans if (newval == oldval) {
17130ef50b4eSJason Evans ret = 0;
17140ef50b4eSJason Evans goto label_return;
17150ef50b4eSJason Evans }
17160ef50b4eSJason Evans if (newval > opt_max_background_threads) {
17170ef50b4eSJason Evans ret = EINVAL;
17180ef50b4eSJason Evans goto label_return;
17190ef50b4eSJason Evans }
17200ef50b4eSJason Evans
17210ef50b4eSJason Evans if (background_thread_enabled()) {
17220ef50b4eSJason Evans background_thread_enabled_set(tsd_tsdn(tsd), false);
17230ef50b4eSJason Evans if (background_threads_disable(tsd)) {
17240ef50b4eSJason Evans ret = EFAULT;
17250ef50b4eSJason Evans goto label_return;
17260ef50b4eSJason Evans }
17270ef50b4eSJason Evans max_background_threads = newval;
17280ef50b4eSJason Evans background_thread_enabled_set(tsd_tsdn(tsd), true);
17290ef50b4eSJason Evans if (background_threads_enable(tsd)) {
17300ef50b4eSJason Evans ret = EFAULT;
17310ef50b4eSJason Evans goto label_return;
17320ef50b4eSJason Evans }
17330ef50b4eSJason Evans } else {
17340ef50b4eSJason Evans max_background_threads = newval;
17350ef50b4eSJason Evans }
17360ef50b4eSJason Evans }
17370ef50b4eSJason Evans ret = 0;
17380ef50b4eSJason Evans label_return:
17390ef50b4eSJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
17400ef50b4eSJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
17410ef50b4eSJason Evans
17420ef50b4eSJason Evans return ret;
17430ef50b4eSJason Evans }
17440ef50b4eSJason Evans
1745f921d10fSJason Evans /******************************************************************************/
1746a4bd5210SJason Evans
CTL_RO_CONFIG_GEN(config_cache_oblivious,bool)1747df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_cache_oblivious, bool)
1748df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_debug, bool)
1749df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_fill, bool)
1750df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_lazy_lock, bool)
1751df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_malloc_conf, const char *)
1752*c5ad8142SEric van Gyzen CTL_RO_CONFIG_GEN(config_opt_safety_checks, bool)
1753df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof, bool)
1754df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof_libgcc, bool)
1755df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_prof_libunwind, bool)
1756df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_stats, bool)
1757df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_utrace, bool)
1758df0d881dSJason Evans CTL_RO_CONFIG_GEN(config_xmalloc, bool)
1759a4bd5210SJason Evans
1760f921d10fSJason Evans /******************************************************************************/
1761a4bd5210SJason Evans
1762f921d10fSJason Evans CTL_RO_NL_GEN(opt_abort, opt_abort, bool)
1763b7eaed25SJason Evans CTL_RO_NL_GEN(opt_abort_conf, opt_abort_conf, bool)
1764*c5ad8142SEric van Gyzen CTL_RO_NL_GEN(opt_confirm_conf, opt_confirm_conf, bool)
17650ef50b4eSJason Evans CTL_RO_NL_GEN(opt_metadata_thp, metadata_thp_mode_names[opt_metadata_thp],
17660ef50b4eSJason Evans const char *)
1767b7eaed25SJason Evans CTL_RO_NL_GEN(opt_retain, opt_retain, bool)
1768f921d10fSJason Evans CTL_RO_NL_GEN(opt_dss, opt_dss, const char *)
1769df0d881dSJason Evans CTL_RO_NL_GEN(opt_narenas, opt_narenas, unsigned)
1770b7eaed25SJason Evans CTL_RO_NL_GEN(opt_percpu_arena, percpu_arena_mode_names[opt_percpu_arena],
1771b7eaed25SJason Evans const char *)
1772*c5ad8142SEric van Gyzen CTL_RO_NL_GEN(opt_oversize_threshold, opt_oversize_threshold, size_t)
1773b7eaed25SJason Evans CTL_RO_NL_GEN(opt_background_thread, opt_background_thread, bool)
17740ef50b4eSJason Evans CTL_RO_NL_GEN(opt_max_background_threads, opt_max_background_threads, size_t)
1775b7eaed25SJason Evans CTL_RO_NL_GEN(opt_dirty_decay_ms, opt_dirty_decay_ms, ssize_t)
1776b7eaed25SJason Evans CTL_RO_NL_GEN(opt_muzzy_decay_ms, opt_muzzy_decay_ms, ssize_t)
1777f921d10fSJason Evans CTL_RO_NL_GEN(opt_stats_print, opt_stats_print, bool)
1778b7eaed25SJason Evans CTL_RO_NL_GEN(opt_stats_print_opts, opt_stats_print_opts, const char *)
1779d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_fill, opt_junk, opt_junk, const char *)
1780f921d10fSJason Evans CTL_RO_NL_CGEN(config_fill, opt_zero, opt_zero, bool)
1781f921d10fSJason Evans CTL_RO_NL_CGEN(config_utrace, opt_utrace, opt_utrace, bool)
1782f921d10fSJason Evans CTL_RO_NL_CGEN(config_xmalloc, opt_xmalloc, opt_xmalloc, bool)
1783b7eaed25SJason Evans CTL_RO_NL_GEN(opt_tcache, opt_tcache, bool)
17840ef50b4eSJason Evans CTL_RO_NL_GEN(opt_thp, thp_mode_names[opt_thp], const char *)
17850ef50b4eSJason Evans CTL_RO_NL_GEN(opt_lg_extent_max_active_fit, opt_lg_extent_max_active_fit,
17860ef50b4eSJason Evans size_t)
1787b7eaed25SJason Evans CTL_RO_NL_GEN(opt_lg_tcache_max, opt_lg_tcache_max, ssize_t)
1788f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof, opt_prof, bool)
1789f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_prefix, opt_prof_prefix, const char *)
1790d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_active, opt_prof_active, bool)
1791d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_thread_active_init,
1792d0e79aa3SJason Evans opt_prof_thread_active_init, bool)
1793f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_lg_prof_sample, opt_lg_prof_sample, size_t)
1794f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_accum, opt_prof_accum, bool)
1795f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_lg_prof_interval, opt_lg_prof_interval, ssize_t)
1796f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_gdump, opt_prof_gdump, bool)
1797f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_final, opt_prof_final, bool)
1798f921d10fSJason Evans CTL_RO_NL_CGEN(config_prof, opt_prof_leak, opt_prof_leak, bool)
1799a4bd5210SJason Evans
1800f921d10fSJason Evans /******************************************************************************/
1801a4bd5210SJason Evans
1802a4bd5210SJason Evans static int
1803*c5ad8142SEric van Gyzen thread_arena_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1804*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
1805a4bd5210SJason Evans int ret;
1806d0e79aa3SJason Evans arena_t *oldarena;
1807a4bd5210SJason Evans unsigned newind, oldind;
1808a4bd5210SJason Evans
1809d0e79aa3SJason Evans oldarena = arena_choose(tsd, NULL);
1810b7eaed25SJason Evans if (oldarena == NULL) {
1811b7eaed25SJason Evans return EAGAIN;
1812b7eaed25SJason Evans }
1813b7eaed25SJason Evans newind = oldind = arena_ind_get(oldarena);
1814a4bd5210SJason Evans WRITE(newind, unsigned);
1815a4bd5210SJason Evans READ(oldind, unsigned);
1816b7eaed25SJason Evans
1817a4bd5210SJason Evans if (newind != oldind) {
1818d0e79aa3SJason Evans arena_t *newarena;
1819a4bd5210SJason Evans
1820b7eaed25SJason Evans if (newind >= narenas_total_get()) {
1821a4bd5210SJason Evans /* New arena index is out of range. */
1822a4bd5210SJason Evans ret = EFAULT;
1823a4bd5210SJason Evans goto label_return;
1824a4bd5210SJason Evans }
1825a4bd5210SJason Evans
1826b7eaed25SJason Evans if (have_percpu_arena &&
1827b7eaed25SJason Evans PERCPU_ARENA_ENABLED(opt_percpu_arena)) {
1828b7eaed25SJason Evans if (newind < percpu_arena_ind_limit(opt_percpu_arena)) {
1829b7eaed25SJason Evans /*
1830b7eaed25SJason Evans * If perCPU arena is enabled, thread_arena
1831b7eaed25SJason Evans * control is not allowed for the auto arena
1832b7eaed25SJason Evans * range.
1833b7eaed25SJason Evans */
1834b7eaed25SJason Evans ret = EPERM;
1835b7eaed25SJason Evans goto label_return;
1836b7eaed25SJason Evans }
1837b7eaed25SJason Evans }
1838b7eaed25SJason Evans
1839a4bd5210SJason Evans /* Initialize arena if necessary. */
18401f0a49e8SJason Evans newarena = arena_get(tsd_tsdn(tsd), newind, true);
1841d0e79aa3SJason Evans if (newarena == NULL) {
1842a4bd5210SJason Evans ret = EAGAIN;
1843a4bd5210SJason Evans goto label_return;
1844a4bd5210SJason Evans }
1845d0e79aa3SJason Evans /* Set new arena/tcache associations. */
1846d0e79aa3SJason Evans arena_migrate(tsd, oldind, newind);
1847b7eaed25SJason Evans if (tcache_available(tsd)) {
1848b7eaed25SJason Evans tcache_arena_reassociate(tsd_tsdn(tsd),
1849b7eaed25SJason Evans tsd_tcachep_get(tsd), newarena);
1850a4bd5210SJason Evans }
1851a4bd5210SJason Evans }
1852a4bd5210SJason Evans
1853a4bd5210SJason Evans ret = 0;
1854a4bd5210SJason Evans label_return:
1855b7eaed25SJason Evans return ret;
1856a4bd5210SJason Evans }
1857a4bd5210SJason Evans
CTL_TSD_RO_NL_CGEN(config_stats,thread_allocated,tsd_thread_allocated_get,uint64_t)1858d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_allocated, tsd_thread_allocated_get,
1859d0e79aa3SJason Evans uint64_t)
1860d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_allocatedp, tsd_thread_allocatedp_get,
1861d0e79aa3SJason Evans uint64_t *)
1862d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocated, tsd_thread_deallocated_get,
1863d0e79aa3SJason Evans uint64_t)
1864d0e79aa3SJason Evans CTL_TSD_RO_NL_CGEN(config_stats, thread_deallocatedp,
1865d0e79aa3SJason Evans tsd_thread_deallocatedp_get, uint64_t *)
1866a4bd5210SJason Evans
1867f921d10fSJason Evans static int
1868*c5ad8142SEric van Gyzen thread_tcache_enabled_ctl(tsd_t *tsd, const size_t *mib,
1869*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
1870*c5ad8142SEric van Gyzen size_t newlen) {
1871f921d10fSJason Evans int ret;
1872f921d10fSJason Evans bool oldval;
1873a4bd5210SJason Evans
1874b7eaed25SJason Evans oldval = tcache_enabled_get(tsd);
1875f921d10fSJason Evans if (newp != NULL) {
1876f921d10fSJason Evans if (newlen != sizeof(bool)) {
1877f921d10fSJason Evans ret = EINVAL;
1878f921d10fSJason Evans goto label_return;
1879f921d10fSJason Evans }
1880b7eaed25SJason Evans tcache_enabled_set(tsd, *(bool *)newp);
1881f921d10fSJason Evans }
1882f921d10fSJason Evans READ(oldval, bool);
1883a4bd5210SJason Evans
1884f921d10fSJason Evans ret = 0;
1885f921d10fSJason Evans label_return:
1886b7eaed25SJason Evans return ret;
1887f921d10fSJason Evans }
1888f921d10fSJason Evans
1889f921d10fSJason Evans static int
thread_tcache_flush_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1890*c5ad8142SEric van Gyzen thread_tcache_flush_ctl(tsd_t *tsd, const size_t *mib,
1891*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
1892*c5ad8142SEric van Gyzen size_t newlen) {
1893f921d10fSJason Evans int ret;
1894f921d10fSJason Evans
1895b7eaed25SJason Evans if (!tcache_available(tsd)) {
1896b7eaed25SJason Evans ret = EFAULT;
1897b7eaed25SJason Evans goto label_return;
1898b7eaed25SJason Evans }
1899f921d10fSJason Evans
1900f921d10fSJason Evans READONLY();
1901f921d10fSJason Evans WRITEONLY();
1902f921d10fSJason Evans
19038b2f5aafSJason Evans tcache_flush(tsd);
1904f921d10fSJason Evans
1905f921d10fSJason Evans ret = 0;
1906f921d10fSJason Evans label_return:
1907b7eaed25SJason Evans return ret;
1908f921d10fSJason Evans }
1909a4bd5210SJason Evans
1910d0e79aa3SJason Evans static int
thread_prof_name_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1911*c5ad8142SEric van Gyzen thread_prof_name_ctl(tsd_t *tsd, const size_t *mib,
1912*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
1913*c5ad8142SEric van Gyzen size_t newlen) {
1914d0e79aa3SJason Evans int ret;
1915d0e79aa3SJason Evans
1916b7eaed25SJason Evans if (!config_prof) {
1917b7eaed25SJason Evans return ENOENT;
1918b7eaed25SJason Evans }
1919d0e79aa3SJason Evans
1920d0e79aa3SJason Evans READ_XOR_WRITE();
1921d0e79aa3SJason Evans
1922d0e79aa3SJason Evans if (newp != NULL) {
1923d0e79aa3SJason Evans if (newlen != sizeof(const char *)) {
1924d0e79aa3SJason Evans ret = EINVAL;
1925d0e79aa3SJason Evans goto label_return;
1926d0e79aa3SJason Evans }
1927d0e79aa3SJason Evans
1928d0e79aa3SJason Evans if ((ret = prof_thread_name_set(tsd, *(const char **)newp)) !=
1929b7eaed25SJason Evans 0) {
1930d0e79aa3SJason Evans goto label_return;
1931b7eaed25SJason Evans }
1932d0e79aa3SJason Evans } else {
19331f0a49e8SJason Evans const char *oldname = prof_thread_name_get(tsd);
1934d0e79aa3SJason Evans READ(oldname, const char *);
1935d0e79aa3SJason Evans }
1936d0e79aa3SJason Evans
1937d0e79aa3SJason Evans ret = 0;
1938d0e79aa3SJason Evans label_return:
1939b7eaed25SJason Evans return ret;
1940d0e79aa3SJason Evans }
1941d0e79aa3SJason Evans
1942d0e79aa3SJason Evans static int
thread_prof_active_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1943*c5ad8142SEric van Gyzen thread_prof_active_ctl(tsd_t *tsd, const size_t *mib,
1944*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
1945*c5ad8142SEric van Gyzen size_t newlen) {
1946d0e79aa3SJason Evans int ret;
1947d0e79aa3SJason Evans bool oldval;
1948d0e79aa3SJason Evans
1949b7eaed25SJason Evans if (!config_prof) {
1950b7eaed25SJason Evans return ENOENT;
1951b7eaed25SJason Evans }
1952d0e79aa3SJason Evans
19531f0a49e8SJason Evans oldval = prof_thread_active_get(tsd);
1954d0e79aa3SJason Evans if (newp != NULL) {
1955d0e79aa3SJason Evans if (newlen != sizeof(bool)) {
1956d0e79aa3SJason Evans ret = EINVAL;
1957d0e79aa3SJason Evans goto label_return;
1958d0e79aa3SJason Evans }
19591f0a49e8SJason Evans if (prof_thread_active_set(tsd, *(bool *)newp)) {
1960d0e79aa3SJason Evans ret = EAGAIN;
1961d0e79aa3SJason Evans goto label_return;
1962d0e79aa3SJason Evans }
1963d0e79aa3SJason Evans }
1964d0e79aa3SJason Evans READ(oldval, bool);
1965d0e79aa3SJason Evans
1966d0e79aa3SJason Evans ret = 0;
1967d0e79aa3SJason Evans label_return:
1968b7eaed25SJason Evans return ret;
1969d0e79aa3SJason Evans }
1970d0e79aa3SJason Evans
1971d0e79aa3SJason Evans /******************************************************************************/
1972d0e79aa3SJason Evans
1973d0e79aa3SJason Evans static int
tcache_create_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1974*c5ad8142SEric van Gyzen tcache_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1975*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
1976d0e79aa3SJason Evans int ret;
1977d0e79aa3SJason Evans unsigned tcache_ind;
1978d0e79aa3SJason Evans
1979d0e79aa3SJason Evans READONLY();
1980bde95144SJason Evans if (tcaches_create(tsd, &tcache_ind)) {
1981d0e79aa3SJason Evans ret = EFAULT;
1982d0e79aa3SJason Evans goto label_return;
1983d0e79aa3SJason Evans }
1984d0e79aa3SJason Evans READ(tcache_ind, unsigned);
1985d0e79aa3SJason Evans
1986d0e79aa3SJason Evans ret = 0;
1987d0e79aa3SJason Evans label_return:
19888244f2aaSJason Evans return ret;
1989d0e79aa3SJason Evans }
1990d0e79aa3SJason Evans
1991d0e79aa3SJason Evans static int
tcache_flush_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)1992*c5ad8142SEric van Gyzen tcache_flush_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
1993*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
1994d0e79aa3SJason Evans int ret;
1995d0e79aa3SJason Evans unsigned tcache_ind;
1996d0e79aa3SJason Evans
1997d0e79aa3SJason Evans WRITEONLY();
1998d0e79aa3SJason Evans tcache_ind = UINT_MAX;
1999d0e79aa3SJason Evans WRITE(tcache_ind, unsigned);
2000d0e79aa3SJason Evans if (tcache_ind == UINT_MAX) {
2001d0e79aa3SJason Evans ret = EFAULT;
2002d0e79aa3SJason Evans goto label_return;
2003d0e79aa3SJason Evans }
2004d0e79aa3SJason Evans tcaches_flush(tsd, tcache_ind);
2005d0e79aa3SJason Evans
2006d0e79aa3SJason Evans ret = 0;
2007d0e79aa3SJason Evans label_return:
2008b7eaed25SJason Evans return ret;
2009d0e79aa3SJason Evans }
2010d0e79aa3SJason Evans
2011d0e79aa3SJason Evans static int
tcache_destroy_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2012*c5ad8142SEric van Gyzen tcache_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2013*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2014d0e79aa3SJason Evans int ret;
2015d0e79aa3SJason Evans unsigned tcache_ind;
2016d0e79aa3SJason Evans
2017d0e79aa3SJason Evans WRITEONLY();
2018d0e79aa3SJason Evans tcache_ind = UINT_MAX;
2019d0e79aa3SJason Evans WRITE(tcache_ind, unsigned);
2020d0e79aa3SJason Evans if (tcache_ind == UINT_MAX) {
2021d0e79aa3SJason Evans ret = EFAULT;
2022d0e79aa3SJason Evans goto label_return;
2023d0e79aa3SJason Evans }
2024d0e79aa3SJason Evans tcaches_destroy(tsd, tcache_ind);
2025d0e79aa3SJason Evans
2026d0e79aa3SJason Evans ret = 0;
2027d0e79aa3SJason Evans label_return:
2028b7eaed25SJason Evans return ret;
2029d0e79aa3SJason Evans }
2030d0e79aa3SJason Evans
2031a4bd5210SJason Evans /******************************************************************************/
2032a4bd5210SJason Evans
2033b7eaed25SJason Evans static int
arena_i_initialized_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2034b7eaed25SJason Evans arena_i_initialized_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2035b7eaed25SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2036b7eaed25SJason Evans int ret;
2037b7eaed25SJason Evans tsdn_t *tsdn = tsd_tsdn(tsd);
2038b7eaed25SJason Evans unsigned arena_ind;
2039b7eaed25SJason Evans bool initialized;
2040b7eaed25SJason Evans
2041b7eaed25SJason Evans READONLY();
2042b7eaed25SJason Evans MIB_UNSIGNED(arena_ind, 1);
204382872ac0SJason Evans
20441f0a49e8SJason Evans malloc_mutex_lock(tsdn, &ctl_mtx);
2045b7eaed25SJason Evans initialized = arenas_i(arena_ind)->initialized;
2046b7eaed25SJason Evans malloc_mutex_unlock(tsdn, &ctl_mtx);
204782872ac0SJason Evans
2048b7eaed25SJason Evans READ(initialized, bool);
2049b7eaed25SJason Evans
2050b7eaed25SJason Evans ret = 0;
2051b7eaed25SJason Evans label_return:
2052b7eaed25SJason Evans return ret;
2053b7eaed25SJason Evans }
2054b7eaed25SJason Evans
2055b7eaed25SJason Evans static void
arena_i_decay(tsdn_t * tsdn,unsigned arena_ind,bool all)2056b7eaed25SJason Evans arena_i_decay(tsdn_t *tsdn, unsigned arena_ind, bool all) {
2057b7eaed25SJason Evans malloc_mutex_lock(tsdn, &ctl_mtx);
2058b7eaed25SJason Evans {
2059b7eaed25SJason Evans unsigned narenas = ctl_arenas->narenas;
2060b7eaed25SJason Evans
2061b7eaed25SJason Evans /*
2062b7eaed25SJason Evans * Access via index narenas is deprecated, and scheduled for
2063b7eaed25SJason Evans * removal in 6.0.0.
2064b7eaed25SJason Evans */
2065b7eaed25SJason Evans if (arena_ind == MALLCTL_ARENAS_ALL || arena_ind == narenas) {
206682872ac0SJason Evans unsigned i;
2067df0d881dSJason Evans VARIABLE_ARRAY(arena_t *, tarenas, narenas);
2068df0d881dSJason Evans
2069b7eaed25SJason Evans for (i = 0; i < narenas; i++) {
20701f0a49e8SJason Evans tarenas[i] = arena_get(tsdn, i, false);
2071b7eaed25SJason Evans }
2072df0d881dSJason Evans
2073df0d881dSJason Evans /*
2074df0d881dSJason Evans * No further need to hold ctl_mtx, since narenas and
2075df0d881dSJason Evans * tarenas contain everything needed below.
2076df0d881dSJason Evans */
20771f0a49e8SJason Evans malloc_mutex_unlock(tsdn, &ctl_mtx);
2078df0d881dSJason Evans
2079df0d881dSJason Evans for (i = 0; i < narenas; i++) {
2080b7eaed25SJason Evans if (tarenas[i] != NULL) {
2081b7eaed25SJason Evans arena_decay(tsdn, tarenas[i], false,
2082b7eaed25SJason Evans all);
2083b7eaed25SJason Evans }
208482872ac0SJason Evans }
208582872ac0SJason Evans } else {
2086df0d881dSJason Evans arena_t *tarena;
2087df0d881dSJason Evans
2088df0d881dSJason Evans assert(arena_ind < narenas);
2089df0d881dSJason Evans
20901f0a49e8SJason Evans tarena = arena_get(tsdn, arena_ind, false);
2091df0d881dSJason Evans
2092df0d881dSJason Evans /* No further need to hold ctl_mtx. */
20931f0a49e8SJason Evans malloc_mutex_unlock(tsdn, &ctl_mtx);
2094df0d881dSJason Evans
2095b7eaed25SJason Evans if (tarena != NULL) {
2096b7eaed25SJason Evans arena_decay(tsdn, tarena, false, all);
2097df0d881dSJason Evans }
209882872ac0SJason Evans }
209982872ac0SJason Evans }
2100df0d881dSJason Evans }
2101df0d881dSJason Evans
2102df0d881dSJason Evans static int
arena_i_decay_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)21031f0a49e8SJason Evans arena_i_decay_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2104b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) {
2105df0d881dSJason Evans int ret;
2106b7eaed25SJason Evans unsigned arena_ind;
2107df0d881dSJason Evans
2108df0d881dSJason Evans READONLY();
2109df0d881dSJason Evans WRITEONLY();
2110b7eaed25SJason Evans MIB_UNSIGNED(arena_ind, 1);
2111b7eaed25SJason Evans arena_i_decay(tsd_tsdn(tsd), arena_ind, false);
211282872ac0SJason Evans
211382872ac0SJason Evans ret = 0;
211482872ac0SJason Evans label_return:
2115b7eaed25SJason Evans return ret;
211682872ac0SJason Evans }
211782872ac0SJason Evans
211882872ac0SJason Evans static int
arena_i_purge_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2119b7eaed25SJason Evans arena_i_purge_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2120b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) {
21211f0a49e8SJason Evans int ret;
21221f0a49e8SJason Evans unsigned arena_ind;
21231f0a49e8SJason Evans
21241f0a49e8SJason Evans READONLY();
21251f0a49e8SJason Evans WRITEONLY();
2126b7eaed25SJason Evans MIB_UNSIGNED(arena_ind, 1);
2127b7eaed25SJason Evans arena_i_decay(tsd_tsdn(tsd), arena_ind, true);
21281f0a49e8SJason Evans
2129b7eaed25SJason Evans ret = 0;
2130b7eaed25SJason Evans label_return:
2131b7eaed25SJason Evans return ret;
2132b7eaed25SJason Evans }
2133b7eaed25SJason Evans
2134b7eaed25SJason Evans static int
arena_i_reset_destroy_helper(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,unsigned * arena_ind,arena_t ** arena)2135b7eaed25SJason Evans arena_i_reset_destroy_helper(tsd_t *tsd, const size_t *mib, size_t miblen,
2136b7eaed25SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen, unsigned *arena_ind,
2137b7eaed25SJason Evans arena_t **arena) {
2138b7eaed25SJason Evans int ret;
2139b7eaed25SJason Evans
2140b7eaed25SJason Evans READONLY();
2141b7eaed25SJason Evans WRITEONLY();
2142b7eaed25SJason Evans MIB_UNSIGNED(*arena_ind, 1);
2143b7eaed25SJason Evans
2144b7eaed25SJason Evans *arena = arena_get(tsd_tsdn(tsd), *arena_ind, false);
2145b7eaed25SJason Evans if (*arena == NULL || arena_is_auto(*arena)) {
21461f0a49e8SJason Evans ret = EFAULT;
21471f0a49e8SJason Evans goto label_return;
21481f0a49e8SJason Evans }
21491f0a49e8SJason Evans
21501f0a49e8SJason Evans ret = 0;
21511f0a49e8SJason Evans label_return:
2152b7eaed25SJason Evans return ret;
2153b7eaed25SJason Evans }
2154b7eaed25SJason Evans
2155b7eaed25SJason Evans static void
arena_reset_prepare_background_thread(tsd_t * tsd,unsigned arena_ind)2156b7eaed25SJason Evans arena_reset_prepare_background_thread(tsd_t *tsd, unsigned arena_ind) {
2157b7eaed25SJason Evans /* Temporarily disable the background thread during arena reset. */
2158b7eaed25SJason Evans if (have_background_thread) {
2159b7eaed25SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &background_thread_lock);
2160b7eaed25SJason Evans if (background_thread_enabled()) {
2161b7eaed25SJason Evans background_thread_info_t *info =
2162*c5ad8142SEric van Gyzen background_thread_info_get(arena_ind);
2163b7eaed25SJason Evans assert(info->state == background_thread_started);
2164b7eaed25SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
2165b7eaed25SJason Evans info->state = background_thread_paused;
2166b7eaed25SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
2167b7eaed25SJason Evans }
2168b7eaed25SJason Evans }
2169b7eaed25SJason Evans }
2170b7eaed25SJason Evans
2171b7eaed25SJason Evans static void
arena_reset_finish_background_thread(tsd_t * tsd,unsigned arena_ind)2172b7eaed25SJason Evans arena_reset_finish_background_thread(tsd_t *tsd, unsigned arena_ind) {
2173b7eaed25SJason Evans if (have_background_thread) {
2174b7eaed25SJason Evans if (background_thread_enabled()) {
2175b7eaed25SJason Evans background_thread_info_t *info =
2176*c5ad8142SEric van Gyzen background_thread_info_get(arena_ind);
21778b2f5aafSJason Evans assert(info->state == background_thread_paused);
2178b7eaed25SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &info->mtx);
2179b7eaed25SJason Evans info->state = background_thread_started;
2180b7eaed25SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &info->mtx);
2181b7eaed25SJason Evans }
2182b7eaed25SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &background_thread_lock);
2183b7eaed25SJason Evans }
2184b7eaed25SJason Evans }
2185b7eaed25SJason Evans
2186b7eaed25SJason Evans static int
arena_i_reset_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2187b7eaed25SJason Evans arena_i_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2188b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) {
2189b7eaed25SJason Evans int ret;
2190b7eaed25SJason Evans unsigned arena_ind;
2191b7eaed25SJason Evans arena_t *arena;
2192b7eaed25SJason Evans
2193b7eaed25SJason Evans ret = arena_i_reset_destroy_helper(tsd, mib, miblen, oldp, oldlenp,
2194b7eaed25SJason Evans newp, newlen, &arena_ind, &arena);
2195b7eaed25SJason Evans if (ret != 0) {
2196b7eaed25SJason Evans return ret;
2197b7eaed25SJason Evans }
2198b7eaed25SJason Evans
2199b7eaed25SJason Evans arena_reset_prepare_background_thread(tsd, arena_ind);
2200b7eaed25SJason Evans arena_reset(tsd, arena);
2201b7eaed25SJason Evans arena_reset_finish_background_thread(tsd, arena_ind);
2202b7eaed25SJason Evans
2203b7eaed25SJason Evans return ret;
2204b7eaed25SJason Evans }
2205b7eaed25SJason Evans
2206b7eaed25SJason Evans static int
arena_i_destroy_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2207b7eaed25SJason Evans arena_i_destroy_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2208b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) {
2209b7eaed25SJason Evans int ret;
2210b7eaed25SJason Evans unsigned arena_ind;
2211b7eaed25SJason Evans arena_t *arena;
2212b7eaed25SJason Evans ctl_arena_t *ctl_darena, *ctl_arena;
2213b7eaed25SJason Evans
2214b7eaed25SJason Evans ret = arena_i_reset_destroy_helper(tsd, mib, miblen, oldp, oldlenp,
2215b7eaed25SJason Evans newp, newlen, &arena_ind, &arena);
2216b7eaed25SJason Evans if (ret != 0) {
2217b7eaed25SJason Evans goto label_return;
2218b7eaed25SJason Evans }
2219b7eaed25SJason Evans
2220b7eaed25SJason Evans if (arena_nthreads_get(arena, false) != 0 || arena_nthreads_get(arena,
2221b7eaed25SJason Evans true) != 0) {
2222b7eaed25SJason Evans ret = EFAULT;
2223b7eaed25SJason Evans goto label_return;
2224b7eaed25SJason Evans }
2225b7eaed25SJason Evans
2226b7eaed25SJason Evans arena_reset_prepare_background_thread(tsd, arena_ind);
2227b7eaed25SJason Evans /* Merge stats after resetting and purging arena. */
2228b7eaed25SJason Evans arena_reset(tsd, arena);
2229b7eaed25SJason Evans arena_decay(tsd_tsdn(tsd), arena, false, true);
2230b7eaed25SJason Evans ctl_darena = arenas_i(MALLCTL_ARENAS_DESTROYED);
2231b7eaed25SJason Evans ctl_darena->initialized = true;
2232b7eaed25SJason Evans ctl_arena_refresh(tsd_tsdn(tsd), arena, ctl_darena, arena_ind, true);
2233b7eaed25SJason Evans /* Destroy arena. */
2234b7eaed25SJason Evans arena_destroy(tsd, arena);
2235b7eaed25SJason Evans ctl_arena = arenas_i(arena_ind);
2236b7eaed25SJason Evans ctl_arena->initialized = false;
2237b7eaed25SJason Evans /* Record arena index for later recycling via arenas.create. */
2238b7eaed25SJason Evans ql_elm_new(ctl_arena, destroyed_link);
2239b7eaed25SJason Evans ql_tail_insert(&ctl_arenas->destroyed, ctl_arena, destroyed_link);
2240b7eaed25SJason Evans arena_reset_finish_background_thread(tsd, arena_ind);
2241b7eaed25SJason Evans
2242b7eaed25SJason Evans assert(ret == 0);
2243b7eaed25SJason Evans label_return:
2244b7eaed25SJason Evans return ret;
22451f0a49e8SJason Evans }
22461f0a49e8SJason Evans
22471f0a49e8SJason Evans static int
arena_i_dss_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)22481f0a49e8SJason Evans arena_i_dss_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2249b7eaed25SJason Evans size_t *oldlenp, void *newp, size_t newlen) {
2250d0e79aa3SJason Evans int ret;
2251d0e79aa3SJason Evans const char *dss = NULL;
2252b7eaed25SJason Evans unsigned arena_ind;
225382872ac0SJason Evans dss_prec_t dss_prec_old = dss_prec_limit;
225482872ac0SJason Evans dss_prec_t dss_prec = dss_prec_limit;
225582872ac0SJason Evans
22561f0a49e8SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
225782872ac0SJason Evans WRITE(dss, const char *);
2258b7eaed25SJason Evans MIB_UNSIGNED(arena_ind, 1);
2259d0e79aa3SJason Evans if (dss != NULL) {
2260d0e79aa3SJason Evans int i;
2261d0e79aa3SJason Evans bool match = false;
2262d0e79aa3SJason Evans
226382872ac0SJason Evans for (i = 0; i < dss_prec_limit; i++) {
226482872ac0SJason Evans if (strcmp(dss_prec_names[i], dss) == 0) {
226582872ac0SJason Evans dss_prec = i;
226682872ac0SJason Evans match = true;
226782872ac0SJason Evans break;
226882872ac0SJason Evans }
226982872ac0SJason Evans }
2270d0e79aa3SJason Evans
2271d0e79aa3SJason Evans if (!match) {
227282872ac0SJason Evans ret = EINVAL;
227382872ac0SJason Evans goto label_return;
227482872ac0SJason Evans }
2275d0e79aa3SJason Evans }
227682872ac0SJason Evans
2277b7eaed25SJason Evans /*
2278b7eaed25SJason Evans * Access via index narenas is deprecated, and scheduled for removal in
2279b7eaed25SJason Evans * 6.0.0.
2280b7eaed25SJason Evans */
2281b7eaed25SJason Evans if (arena_ind == MALLCTL_ARENAS_ALL || arena_ind ==
2282b7eaed25SJason Evans ctl_arenas->narenas) {
2283b7eaed25SJason Evans if (dss_prec != dss_prec_limit &&
2284b7eaed25SJason Evans extent_dss_prec_set(dss_prec)) {
2285b7eaed25SJason Evans ret = EFAULT;
2286b7eaed25SJason Evans goto label_return;
2287b7eaed25SJason Evans }
2288b7eaed25SJason Evans dss_prec_old = extent_dss_prec_get();
2289b7eaed25SJason Evans } else {
22901f0a49e8SJason Evans arena_t *arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
2291d0e79aa3SJason Evans if (arena == NULL || (dss_prec != dss_prec_limit &&
2292b7eaed25SJason Evans arena_dss_prec_set(arena, dss_prec))) {
2293d0e79aa3SJason Evans ret = EFAULT;
2294d0e79aa3SJason Evans goto label_return;
229582872ac0SJason Evans }
2296b7eaed25SJason Evans dss_prec_old = arena_dss_prec_get(arena);
2297d0e79aa3SJason Evans }
2298d0e79aa3SJason Evans
229982872ac0SJason Evans dss = dss_prec_names[dss_prec_old];
230082872ac0SJason Evans READ(dss, const char *);
2301d0e79aa3SJason Evans
2302d0e79aa3SJason Evans ret = 0;
2303d0e79aa3SJason Evans label_return:
23041f0a49e8SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
2305b7eaed25SJason Evans return ret;
2306d0e79aa3SJason Evans }
2307d0e79aa3SJason Evans
2308d0e79aa3SJason Evans static int
arena_i_decay_ms_ctl_impl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,bool dirty)2309b7eaed25SJason Evans arena_i_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib, size_t miblen,
2310b7eaed25SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen, bool dirty) {
2311d0e79aa3SJason Evans int ret;
2312b7eaed25SJason Evans unsigned arena_ind;
2313d0e79aa3SJason Evans arena_t *arena;
2314d0e79aa3SJason Evans
2315b7eaed25SJason Evans MIB_UNSIGNED(arena_ind, 1);
23161f0a49e8SJason Evans arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
2317d0e79aa3SJason Evans if (arena == NULL) {
231882872ac0SJason Evans ret = EFAULT;
231982872ac0SJason Evans goto label_return;
232082872ac0SJason Evans }
232182872ac0SJason Evans
2322d0e79aa3SJason Evans if (oldp != NULL && oldlenp != NULL) {
2323b7eaed25SJason Evans size_t oldval = dirty ? arena_dirty_decay_ms_get(arena) :
2324b7eaed25SJason Evans arena_muzzy_decay_ms_get(arena);
2325d0e79aa3SJason Evans READ(oldval, ssize_t);
2326d0e79aa3SJason Evans }
2327d0e79aa3SJason Evans if (newp != NULL) {
2328d0e79aa3SJason Evans if (newlen != sizeof(ssize_t)) {
2329d0e79aa3SJason Evans ret = EINVAL;
2330d0e79aa3SJason Evans goto label_return;
2331d0e79aa3SJason Evans }
2332*c5ad8142SEric van Gyzen if (arena_is_huge(arena_ind) && *(ssize_t *)newp > 0) {
2333*c5ad8142SEric van Gyzen /*
2334*c5ad8142SEric van Gyzen * By default the huge arena purges eagerly. If it is
2335*c5ad8142SEric van Gyzen * set to non-zero decay time afterwards, background
2336*c5ad8142SEric van Gyzen * thread might be needed.
2337*c5ad8142SEric van Gyzen */
2338*c5ad8142SEric van Gyzen if (background_thread_create(tsd, arena_ind)) {
2339*c5ad8142SEric van Gyzen ret = EFAULT;
2340*c5ad8142SEric van Gyzen goto label_return;
2341*c5ad8142SEric van Gyzen }
2342*c5ad8142SEric van Gyzen }
2343b7eaed25SJason Evans if (dirty ? arena_dirty_decay_ms_set(tsd_tsdn(tsd), arena,
2344b7eaed25SJason Evans *(ssize_t *)newp) : arena_muzzy_decay_ms_set(tsd_tsdn(tsd),
2345b7eaed25SJason Evans arena, *(ssize_t *)newp)) {
2346d0e79aa3SJason Evans ret = EFAULT;
2347d0e79aa3SJason Evans goto label_return;
2348d0e79aa3SJason Evans }
2349d0e79aa3SJason Evans }
2350d0e79aa3SJason Evans
2351d0e79aa3SJason Evans ret = 0;
2352d0e79aa3SJason Evans label_return:
2353b7eaed25SJason Evans return ret;
2354d0e79aa3SJason Evans }
2355d0e79aa3SJason Evans
2356d0e79aa3SJason Evans static int
arena_i_dirty_decay_ms_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2357b7eaed25SJason Evans arena_i_dirty_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2358b7eaed25SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2359b7eaed25SJason Evans return arena_i_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp,
2360b7eaed25SJason Evans newlen, true);
2361df0d881dSJason Evans }
2362df0d881dSJason Evans
2363df0d881dSJason Evans static int
arena_i_muzzy_decay_ms_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2364b7eaed25SJason Evans arena_i_muzzy_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2365b7eaed25SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2366b7eaed25SJason Evans return arena_i_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp,
2367b7eaed25SJason Evans newlen, false);
2368b7eaed25SJason Evans }
2369b7eaed25SJason Evans
2370b7eaed25SJason Evans static int
arena_i_extent_hooks_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2371b7eaed25SJason Evans arena_i_extent_hooks_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2372b7eaed25SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2373d0e79aa3SJason Evans int ret;
2374b7eaed25SJason Evans unsigned arena_ind;
2375d0e79aa3SJason Evans arena_t *arena;
2376d0e79aa3SJason Evans
23771f0a49e8SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
2378b7eaed25SJason Evans MIB_UNSIGNED(arena_ind, 1);
23790ef50b4eSJason Evans if (arena_ind < narenas_total_get()) {
2380b7eaed25SJason Evans extent_hooks_t *old_extent_hooks;
23810ef50b4eSJason Evans arena = arena_get(tsd_tsdn(tsd), arena_ind, false);
23820ef50b4eSJason Evans if (arena == NULL) {
23830ef50b4eSJason Evans if (arena_ind >= narenas_auto) {
23840ef50b4eSJason Evans ret = EFAULT;
23850ef50b4eSJason Evans goto label_return;
23860ef50b4eSJason Evans }
23870ef50b4eSJason Evans old_extent_hooks =
23880ef50b4eSJason Evans (extent_hooks_t *)&extent_hooks_default;
23890ef50b4eSJason Evans READ(old_extent_hooks, extent_hooks_t *);
23900ef50b4eSJason Evans if (newp != NULL) {
23910ef50b4eSJason Evans /* Initialize a new arena as a side effect. */
23920ef50b4eSJason Evans extent_hooks_t *new_extent_hooks
23930ef50b4eSJason Evans JEMALLOC_CC_SILENCE_INIT(NULL);
23940ef50b4eSJason Evans WRITE(new_extent_hooks, extent_hooks_t *);
23950ef50b4eSJason Evans arena = arena_init(tsd_tsdn(tsd), arena_ind,
23960ef50b4eSJason Evans new_extent_hooks);
23970ef50b4eSJason Evans if (arena == NULL) {
23980ef50b4eSJason Evans ret = EFAULT;
23990ef50b4eSJason Evans goto label_return;
24000ef50b4eSJason Evans }
24010ef50b4eSJason Evans }
24020ef50b4eSJason Evans } else {
24030ef50b4eSJason Evans if (newp != NULL) {
2404b7eaed25SJason Evans extent_hooks_t *new_extent_hooks
2405b7eaed25SJason Evans JEMALLOC_CC_SILENCE_INIT(NULL);
2406b7eaed25SJason Evans WRITE(new_extent_hooks, extent_hooks_t *);
2407b7eaed25SJason Evans old_extent_hooks = extent_hooks_set(tsd, arena,
2408b7eaed25SJason Evans new_extent_hooks);
2409b7eaed25SJason Evans READ(old_extent_hooks, extent_hooks_t *);
2410d0e79aa3SJason Evans } else {
24110ef50b4eSJason Evans old_extent_hooks = extent_hooks_get(arena);
2412b7eaed25SJason Evans READ(old_extent_hooks, extent_hooks_t *);
2413d0e79aa3SJason Evans }
24140ef50b4eSJason Evans }
2415d0e79aa3SJason Evans } else {
2416d0e79aa3SJason Evans ret = EFAULT;
2417d0e79aa3SJason Evans goto label_return;
2418d0e79aa3SJason Evans }
241982872ac0SJason Evans ret = 0;
242082872ac0SJason Evans label_return:
24211f0a49e8SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
2422b7eaed25SJason Evans return ret;
242382872ac0SJason Evans }
242482872ac0SJason Evans
24250ef50b4eSJason Evans static int
arena_i_retain_grow_limit_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2426*c5ad8142SEric van Gyzen arena_i_retain_grow_limit_ctl(tsd_t *tsd, const size_t *mib,
2427*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
2428*c5ad8142SEric van Gyzen size_t newlen) {
24290ef50b4eSJason Evans int ret;
24300ef50b4eSJason Evans unsigned arena_ind;
24310ef50b4eSJason Evans arena_t *arena;
24320ef50b4eSJason Evans
24330ef50b4eSJason Evans if (!opt_retain) {
24340ef50b4eSJason Evans /* Only relevant when retain is enabled. */
24350ef50b4eSJason Evans return ENOENT;
24360ef50b4eSJason Evans }
24370ef50b4eSJason Evans
24380ef50b4eSJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
24390ef50b4eSJason Evans MIB_UNSIGNED(arena_ind, 1);
24400ef50b4eSJason Evans if (arena_ind < narenas_total_get() && (arena =
24410ef50b4eSJason Evans arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) {
24420ef50b4eSJason Evans size_t old_limit, new_limit;
24430ef50b4eSJason Evans if (newp != NULL) {
24440ef50b4eSJason Evans WRITE(new_limit, size_t);
24450ef50b4eSJason Evans }
24460ef50b4eSJason Evans bool err = arena_retain_grow_limit_get_set(tsd, arena,
24470ef50b4eSJason Evans &old_limit, newp != NULL ? &new_limit : NULL);
24480ef50b4eSJason Evans if (!err) {
24490ef50b4eSJason Evans READ(old_limit, size_t);
24500ef50b4eSJason Evans ret = 0;
24510ef50b4eSJason Evans } else {
24520ef50b4eSJason Evans ret = EFAULT;
24530ef50b4eSJason Evans }
24540ef50b4eSJason Evans } else {
24550ef50b4eSJason Evans ret = EFAULT;
24560ef50b4eSJason Evans }
24570ef50b4eSJason Evans label_return:
24580ef50b4eSJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
24590ef50b4eSJason Evans return ret;
24600ef50b4eSJason Evans }
24610ef50b4eSJason Evans
246282872ac0SJason Evans static const ctl_named_node_t *
arena_i_index(tsdn_t * tsdn,const size_t * mib,size_t miblen,size_t i)2463*c5ad8142SEric van Gyzen arena_i_index(tsdn_t *tsdn, const size_t *mib, size_t miblen,
2464*c5ad8142SEric van Gyzen size_t i) {
246582872ac0SJason Evans const ctl_named_node_t *ret;
246682872ac0SJason Evans
24671f0a49e8SJason Evans malloc_mutex_lock(tsdn, &ctl_mtx);
2468b7eaed25SJason Evans switch (i) {
2469b7eaed25SJason Evans case MALLCTL_ARENAS_ALL:
2470b7eaed25SJason Evans case MALLCTL_ARENAS_DESTROYED:
2471b7eaed25SJason Evans break;
2472b7eaed25SJason Evans default:
2473b7eaed25SJason Evans if (i > ctl_arenas->narenas) {
247482872ac0SJason Evans ret = NULL;
247582872ac0SJason Evans goto label_return;
247682872ac0SJason Evans }
2477b7eaed25SJason Evans break;
2478b7eaed25SJason Evans }
247982872ac0SJason Evans
248082872ac0SJason Evans ret = super_arena_i_node;
248182872ac0SJason Evans label_return:
24821f0a49e8SJason Evans malloc_mutex_unlock(tsdn, &ctl_mtx);
2483b7eaed25SJason Evans return ret;
248482872ac0SJason Evans }
248582872ac0SJason Evans
248682872ac0SJason Evans /******************************************************************************/
248782872ac0SJason Evans
248882872ac0SJason Evans static int
arenas_narenas_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2489*c5ad8142SEric van Gyzen arenas_narenas_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2490*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
249182872ac0SJason Evans int ret;
249282872ac0SJason Evans unsigned narenas;
249382872ac0SJason Evans
24941f0a49e8SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
249582872ac0SJason Evans READONLY();
249682872ac0SJason Evans if (*oldlenp != sizeof(unsigned)) {
249782872ac0SJason Evans ret = EINVAL;
249882872ac0SJason Evans goto label_return;
249982872ac0SJason Evans }
2500b7eaed25SJason Evans narenas = ctl_arenas->narenas;
250182872ac0SJason Evans READ(narenas, unsigned);
250282872ac0SJason Evans
250382872ac0SJason Evans ret = 0;
250482872ac0SJason Evans label_return:
25051f0a49e8SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
2506b7eaed25SJason Evans return ret;
250782872ac0SJason Evans }
2508a4bd5210SJason Evans
2509a4bd5210SJason Evans static int
arenas_decay_ms_ctl_impl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen,bool dirty)2510*c5ad8142SEric van Gyzen arenas_decay_ms_ctl_impl(tsd_t *tsd, const size_t *mib,
2511*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
2512*c5ad8142SEric van Gyzen size_t newlen, bool dirty) {
2513d0e79aa3SJason Evans int ret;
2514d0e79aa3SJason Evans
2515d0e79aa3SJason Evans if (oldp != NULL && oldlenp != NULL) {
2516b7eaed25SJason Evans size_t oldval = (dirty ? arena_dirty_decay_ms_default_get() :
2517b7eaed25SJason Evans arena_muzzy_decay_ms_default_get());
2518d0e79aa3SJason Evans READ(oldval, ssize_t);
2519d0e79aa3SJason Evans }
2520d0e79aa3SJason Evans if (newp != NULL) {
2521d0e79aa3SJason Evans if (newlen != sizeof(ssize_t)) {
2522d0e79aa3SJason Evans ret = EINVAL;
2523d0e79aa3SJason Evans goto label_return;
2524d0e79aa3SJason Evans }
2525b7eaed25SJason Evans if (dirty ? arena_dirty_decay_ms_default_set(*(ssize_t *)newp)
2526b7eaed25SJason Evans : arena_muzzy_decay_ms_default_set(*(ssize_t *)newp)) {
2527d0e79aa3SJason Evans ret = EFAULT;
2528d0e79aa3SJason Evans goto label_return;
2529d0e79aa3SJason Evans }
2530d0e79aa3SJason Evans }
2531d0e79aa3SJason Evans
2532d0e79aa3SJason Evans ret = 0;
2533d0e79aa3SJason Evans label_return:
2534b7eaed25SJason Evans return ret;
2535d0e79aa3SJason Evans }
2536d0e79aa3SJason Evans
2537df0d881dSJason Evans static int
arenas_dirty_decay_ms_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2538b7eaed25SJason Evans arenas_dirty_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2539b7eaed25SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2540b7eaed25SJason Evans return arenas_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp,
2541b7eaed25SJason Evans newlen, true);
2542df0d881dSJason Evans }
2543df0d881dSJason Evans
2544b7eaed25SJason Evans static int
arenas_muzzy_decay_ms_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2545b7eaed25SJason Evans arenas_muzzy_decay_ms_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2546b7eaed25SJason Evans void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2547b7eaed25SJason Evans return arenas_decay_ms_ctl_impl(tsd, mib, miblen, oldp, oldlenp, newp,
2548b7eaed25SJason Evans newlen, false);
2549df0d881dSJason Evans }
2550df0d881dSJason Evans
CTL_RO_NL_GEN(arenas_quantum,QUANTUM,size_t)2551a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_quantum, QUANTUM, size_t)
2552a4bd5210SJason Evans CTL_RO_NL_GEN(arenas_page, PAGE, size_t)
2553b7eaed25SJason Evans CTL_RO_NL_GEN(arenas_tcache_max, tcache_maxclass, size_t)
2554*c5ad8142SEric van Gyzen CTL_RO_NL_GEN(arenas_nbins, SC_NBINS, unsigned)
2555b7eaed25SJason Evans CTL_RO_NL_GEN(arenas_nhbins, nhbins, unsigned)
25560ef50b4eSJason Evans CTL_RO_NL_GEN(arenas_bin_i_size, bin_infos[mib[2]].reg_size, size_t)
25570ef50b4eSJason Evans CTL_RO_NL_GEN(arenas_bin_i_nregs, bin_infos[mib[2]].nregs, uint32_t)
25580ef50b4eSJason Evans CTL_RO_NL_GEN(arenas_bin_i_slab_size, bin_infos[mib[2]].slab_size, size_t)
2559*c5ad8142SEric van Gyzen CTL_RO_NL_GEN(arenas_bin_i_nshards, bin_infos[mib[2]].n_shards, uint32_t)
2560f921d10fSJason Evans static const ctl_named_node_t *
2561*c5ad8142SEric van Gyzen arenas_bin_i_index(tsdn_t *tsdn, const size_t *mib,
2562*c5ad8142SEric van Gyzen size_t miblen, size_t i) {
2563*c5ad8142SEric van Gyzen if (i > SC_NBINS) {
2564b7eaed25SJason Evans return NULL;
2565b7eaed25SJason Evans }
2566b7eaed25SJason Evans return super_arenas_bin_i_node;
2567f921d10fSJason Evans }
2568f921d10fSJason Evans
2569*c5ad8142SEric van Gyzen CTL_RO_NL_GEN(arenas_nlextents, SC_NSIZES - SC_NBINS, unsigned)
2570*c5ad8142SEric van Gyzen CTL_RO_NL_GEN(arenas_lextent_i_size, sz_index2size(SC_NBINS+(szind_t)mib[2]),
2571df0d881dSJason Evans size_t)
2572d0e79aa3SJason Evans static const ctl_named_node_t *
arenas_lextent_i_index(tsdn_t * tsdn,const size_t * mib,size_t miblen,size_t i)2573*c5ad8142SEric van Gyzen arenas_lextent_i_index(tsdn_t *tsdn, const size_t *mib,
2574*c5ad8142SEric van Gyzen size_t miblen, size_t i) {
2575*c5ad8142SEric van Gyzen if (i > SC_NSIZES - SC_NBINS) {
2576b7eaed25SJason Evans return NULL;
2577b7eaed25SJason Evans }
2578b7eaed25SJason Evans return super_arenas_lextent_i_node;
257982872ac0SJason Evans }
258082872ac0SJason Evans
258182872ac0SJason Evans static int
arenas_create_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2582*c5ad8142SEric van Gyzen arenas_create_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2583*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
258482872ac0SJason Evans int ret;
2585b7eaed25SJason Evans extent_hooks_t *extent_hooks;
2586b7eaed25SJason Evans unsigned arena_ind;
258782872ac0SJason Evans
25881f0a49e8SJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
2589b7eaed25SJason Evans
2590b7eaed25SJason Evans extent_hooks = (extent_hooks_t *)&extent_hooks_default;
2591b7eaed25SJason Evans WRITE(extent_hooks, extent_hooks_t *);
25928b2f5aafSJason Evans if ((arena_ind = ctl_arena_init(tsd, extent_hooks)) == UINT_MAX) {
259382872ac0SJason Evans ret = EAGAIN;
2594a4bd5210SJason Evans goto label_return;
2595a4bd5210SJason Evans }
2596b7eaed25SJason Evans READ(arena_ind, unsigned);
2597a4bd5210SJason Evans
2598a4bd5210SJason Evans ret = 0;
2599a4bd5210SJason Evans label_return:
26001f0a49e8SJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
2601b7eaed25SJason Evans return ret;
2602a4bd5210SJason Evans }
2603a4bd5210SJason Evans
26040ef50b4eSJason Evans static int
arenas_lookup_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2605*c5ad8142SEric van Gyzen arenas_lookup_ctl(tsd_t *tsd, const size_t *mib,
2606*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
2607*c5ad8142SEric van Gyzen size_t newlen) {
26080ef50b4eSJason Evans int ret;
26090ef50b4eSJason Evans unsigned arena_ind;
26100ef50b4eSJason Evans void *ptr;
26110ef50b4eSJason Evans extent_t *extent;
26120ef50b4eSJason Evans arena_t *arena;
26130ef50b4eSJason Evans
26140ef50b4eSJason Evans ptr = NULL;
26150ef50b4eSJason Evans ret = EINVAL;
26160ef50b4eSJason Evans malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
26170ef50b4eSJason Evans WRITE(ptr, void *);
26180ef50b4eSJason Evans extent = iealloc(tsd_tsdn(tsd), ptr);
26190ef50b4eSJason Evans if (extent == NULL)
26200ef50b4eSJason Evans goto label_return;
26210ef50b4eSJason Evans
26220ef50b4eSJason Evans arena = extent_arena_get(extent);
26230ef50b4eSJason Evans if (arena == NULL)
26240ef50b4eSJason Evans goto label_return;
26250ef50b4eSJason Evans
26260ef50b4eSJason Evans arena_ind = arena_ind_get(arena);
26270ef50b4eSJason Evans READ(arena_ind, unsigned);
26280ef50b4eSJason Evans
26290ef50b4eSJason Evans ret = 0;
26300ef50b4eSJason Evans label_return:
26310ef50b4eSJason Evans malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
26320ef50b4eSJason Evans return ret;
26330ef50b4eSJason Evans }
26340ef50b4eSJason Evans
2635a4bd5210SJason Evans /******************************************************************************/
2636a4bd5210SJason Evans
2637a4bd5210SJason Evans static int
prof_thread_active_init_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2638*c5ad8142SEric van Gyzen prof_thread_active_init_ctl(tsd_t *tsd, const size_t *mib,
2639*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp,
2640*c5ad8142SEric van Gyzen size_t newlen) {
26411f0a49e8SJason Evans int ret;
26421f0a49e8SJason Evans bool oldval;
26431f0a49e8SJason Evans
2644b7eaed25SJason Evans if (!config_prof) {
2645b7eaed25SJason Evans return ENOENT;
2646b7eaed25SJason Evans }
26471f0a49e8SJason Evans
26481f0a49e8SJason Evans if (newp != NULL) {
26491f0a49e8SJason Evans if (newlen != sizeof(bool)) {
26501f0a49e8SJason Evans ret = EINVAL;
26511f0a49e8SJason Evans goto label_return;
26521f0a49e8SJason Evans }
26531f0a49e8SJason Evans oldval = prof_thread_active_init_set(tsd_tsdn(tsd),
26541f0a49e8SJason Evans *(bool *)newp);
2655b7eaed25SJason Evans } else {
26561f0a49e8SJason Evans oldval = prof_thread_active_init_get(tsd_tsdn(tsd));
2657b7eaed25SJason Evans }
26581f0a49e8SJason Evans READ(oldval, bool);
26591f0a49e8SJason Evans
26601f0a49e8SJason Evans ret = 0;
26611f0a49e8SJason Evans label_return:
2662b7eaed25SJason Evans return ret;
26631f0a49e8SJason Evans }
26641f0a49e8SJason Evans
26651f0a49e8SJason Evans static int
prof_active_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2666*c5ad8142SEric van Gyzen prof_active_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2667*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2668d0e79aa3SJason Evans int ret;
2669d0e79aa3SJason Evans bool oldval;
2670d0e79aa3SJason Evans
2671b7eaed25SJason Evans if (!config_prof) {
2672b7eaed25SJason Evans return ENOENT;
2673b7eaed25SJason Evans }
2674d0e79aa3SJason Evans
2675d0e79aa3SJason Evans if (newp != NULL) {
2676d0e79aa3SJason Evans if (newlen != sizeof(bool)) {
2677d0e79aa3SJason Evans ret = EINVAL;
2678d0e79aa3SJason Evans goto label_return;
2679d0e79aa3SJason Evans }
26801f0a49e8SJason Evans oldval = prof_active_set(tsd_tsdn(tsd), *(bool *)newp);
2681b7eaed25SJason Evans } else {
26821f0a49e8SJason Evans oldval = prof_active_get(tsd_tsdn(tsd));
2683b7eaed25SJason Evans }
2684d0e79aa3SJason Evans READ(oldval, bool);
2685d0e79aa3SJason Evans
2686d0e79aa3SJason Evans ret = 0;
2687d0e79aa3SJason Evans label_return:
2688b7eaed25SJason Evans return ret;
2689d0e79aa3SJason Evans }
2690d0e79aa3SJason Evans
2691d0e79aa3SJason Evans static int
prof_dump_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2692*c5ad8142SEric van Gyzen prof_dump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2693*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2694a4bd5210SJason Evans int ret;
2695a4bd5210SJason Evans const char *filename = NULL;
2696a4bd5210SJason Evans
2697b7eaed25SJason Evans if (!config_prof) {
2698b7eaed25SJason Evans return ENOENT;
2699b7eaed25SJason Evans }
2700a4bd5210SJason Evans
2701a4bd5210SJason Evans WRITEONLY();
2702a4bd5210SJason Evans WRITE(filename, const char *);
2703a4bd5210SJason Evans
27041f0a49e8SJason Evans if (prof_mdump(tsd, filename)) {
2705a4bd5210SJason Evans ret = EFAULT;
2706a4bd5210SJason Evans goto label_return;
2707a4bd5210SJason Evans }
2708a4bd5210SJason Evans
2709a4bd5210SJason Evans ret = 0;
2710a4bd5210SJason Evans label_return:
2711b7eaed25SJason Evans return ret;
2712a4bd5210SJason Evans }
2713a4bd5210SJason Evans
2714d0e79aa3SJason Evans static int
prof_gdump_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2715*c5ad8142SEric van Gyzen prof_gdump_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2716*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2717d0e79aa3SJason Evans int ret;
2718d0e79aa3SJason Evans bool oldval;
2719d0e79aa3SJason Evans
2720b7eaed25SJason Evans if (!config_prof) {
2721b7eaed25SJason Evans return ENOENT;
2722b7eaed25SJason Evans }
2723d0e79aa3SJason Evans
2724d0e79aa3SJason Evans if (newp != NULL) {
2725d0e79aa3SJason Evans if (newlen != sizeof(bool)) {
2726d0e79aa3SJason Evans ret = EINVAL;
2727d0e79aa3SJason Evans goto label_return;
2728d0e79aa3SJason Evans }
27291f0a49e8SJason Evans oldval = prof_gdump_set(tsd_tsdn(tsd), *(bool *)newp);
2730b7eaed25SJason Evans } else {
27311f0a49e8SJason Evans oldval = prof_gdump_get(tsd_tsdn(tsd));
2732b7eaed25SJason Evans }
2733d0e79aa3SJason Evans READ(oldval, bool);
2734d0e79aa3SJason Evans
2735d0e79aa3SJason Evans ret = 0;
2736d0e79aa3SJason Evans label_return:
2737b7eaed25SJason Evans return ret;
2738d0e79aa3SJason Evans }
2739d0e79aa3SJason Evans
2740d0e79aa3SJason Evans static int
prof_reset_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2741*c5ad8142SEric van Gyzen prof_reset_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
2742*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
2743d0e79aa3SJason Evans int ret;
2744d0e79aa3SJason Evans size_t lg_sample = lg_prof_sample;
2745d0e79aa3SJason Evans
2746b7eaed25SJason Evans if (!config_prof) {
2747b7eaed25SJason Evans return ENOENT;
2748b7eaed25SJason Evans }
2749d0e79aa3SJason Evans
2750d0e79aa3SJason Evans WRITEONLY();
2751d0e79aa3SJason Evans WRITE(lg_sample, size_t);
2752b7eaed25SJason Evans if (lg_sample >= (sizeof(uint64_t) << 3)) {
2753d0e79aa3SJason Evans lg_sample = (sizeof(uint64_t) << 3) - 1;
2754b7eaed25SJason Evans }
2755d0e79aa3SJason Evans
2756bde95144SJason Evans prof_reset(tsd, lg_sample);
2757d0e79aa3SJason Evans
2758d0e79aa3SJason Evans ret = 0;
2759d0e79aa3SJason Evans label_return:
2760b7eaed25SJason Evans return ret;
2761d0e79aa3SJason Evans }
2762d0e79aa3SJason Evans
CTL_RO_NL_CGEN(config_prof,prof_interval,prof_interval,uint64_t)2763a4bd5210SJason Evans CTL_RO_NL_CGEN(config_prof, prof_interval, prof_interval, uint64_t)
2764d0e79aa3SJason Evans CTL_RO_NL_CGEN(config_prof, lg_prof_sample, lg_prof_sample, size_t)
2765a4bd5210SJason Evans
2766*c5ad8142SEric van Gyzen static int
2767*c5ad8142SEric van Gyzen prof_log_start_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2768*c5ad8142SEric van Gyzen size_t *oldlenp, void *newp, size_t newlen) {
2769*c5ad8142SEric van Gyzen int ret;
2770*c5ad8142SEric van Gyzen
2771*c5ad8142SEric van Gyzen const char *filename = NULL;
2772*c5ad8142SEric van Gyzen
2773*c5ad8142SEric van Gyzen if (!config_prof) {
2774*c5ad8142SEric van Gyzen return ENOENT;
2775*c5ad8142SEric van Gyzen }
2776*c5ad8142SEric van Gyzen
2777*c5ad8142SEric van Gyzen WRITEONLY();
2778*c5ad8142SEric van Gyzen WRITE(filename, const char *);
2779*c5ad8142SEric van Gyzen
2780*c5ad8142SEric van Gyzen if (prof_log_start(tsd_tsdn(tsd), filename)) {
2781*c5ad8142SEric van Gyzen ret = EFAULT;
2782*c5ad8142SEric van Gyzen goto label_return;
2783*c5ad8142SEric van Gyzen }
2784*c5ad8142SEric van Gyzen
2785*c5ad8142SEric van Gyzen ret = 0;
2786*c5ad8142SEric van Gyzen label_return:
2787*c5ad8142SEric van Gyzen return ret;
2788*c5ad8142SEric van Gyzen }
2789*c5ad8142SEric van Gyzen
2790*c5ad8142SEric van Gyzen static int
prof_log_stop_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2791*c5ad8142SEric van Gyzen prof_log_stop_ctl(tsd_t *tsd, const size_t *mib, size_t miblen, void *oldp,
2792*c5ad8142SEric van Gyzen size_t *oldlenp, void *newp, size_t newlen) {
2793*c5ad8142SEric van Gyzen if (!config_prof) {
2794*c5ad8142SEric van Gyzen return ENOENT;
2795*c5ad8142SEric van Gyzen }
2796*c5ad8142SEric van Gyzen
2797*c5ad8142SEric van Gyzen if (prof_log_stop(tsd_tsdn(tsd))) {
2798*c5ad8142SEric van Gyzen return EFAULT;
2799*c5ad8142SEric van Gyzen }
2800*c5ad8142SEric van Gyzen
2801*c5ad8142SEric van Gyzen return 0;
2802*c5ad8142SEric van Gyzen }
2803*c5ad8142SEric van Gyzen
2804a4bd5210SJason Evans /******************************************************************************/
2805a4bd5210SJason Evans
2806b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_allocated, ctl_stats->allocated, size_t)
2807b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_active, ctl_stats->active, size_t)
2808b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_metadata, ctl_stats->metadata, size_t)
28090ef50b4eSJason Evans CTL_RO_CGEN(config_stats, stats_metadata_thp, ctl_stats->metadata_thp, size_t)
2810b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_resident, ctl_stats->resident, size_t)
2811b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_mapped, ctl_stats->mapped, size_t)
2812b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_retained, ctl_stats->retained, size_t)
2813f921d10fSJason Evans
2814b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_background_thread_num_threads,
2815b7eaed25SJason Evans ctl_stats->background_thread.num_threads, size_t)
2816b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_background_thread_num_runs,
2817b7eaed25SJason Evans ctl_stats->background_thread.num_runs, uint64_t)
2818b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_background_thread_run_interval,
2819b7eaed25SJason Evans nstime_ns(&ctl_stats->background_thread.run_interval), uint64_t)
2820b7eaed25SJason Evans
2821b7eaed25SJason Evans CTL_RO_GEN(stats_arenas_i_dss, arenas_i(mib[2])->dss, const char *)
2822b7eaed25SJason Evans CTL_RO_GEN(stats_arenas_i_dirty_decay_ms, arenas_i(mib[2])->dirty_decay_ms,
2823d0e79aa3SJason Evans ssize_t)
2824b7eaed25SJason Evans CTL_RO_GEN(stats_arenas_i_muzzy_decay_ms, arenas_i(mib[2])->muzzy_decay_ms,
2825df0d881dSJason Evans ssize_t)
2826b7eaed25SJason Evans CTL_RO_GEN(stats_arenas_i_nthreads, arenas_i(mib[2])->nthreads, unsigned)
2827b7eaed25SJason Evans CTL_RO_GEN(stats_arenas_i_uptime,
2828b7eaed25SJason Evans nstime_ns(&arenas_i(mib[2])->astats->astats.uptime), uint64_t)
2829b7eaed25SJason Evans CTL_RO_GEN(stats_arenas_i_pactive, arenas_i(mib[2])->pactive, size_t)
2830b7eaed25SJason Evans CTL_RO_GEN(stats_arenas_i_pdirty, arenas_i(mib[2])->pdirty, size_t)
2831b7eaed25SJason Evans CTL_RO_GEN(stats_arenas_i_pmuzzy, arenas_i(mib[2])->pmuzzy, size_t)
2832f921d10fSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_mapped,
2833b7eaed25SJason Evans atomic_load_zu(&arenas_i(mib[2])->astats->astats.mapped, ATOMIC_RELAXED),
2834b7eaed25SJason Evans size_t)
28351f0a49e8SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_retained,
2836b7eaed25SJason Evans atomic_load_zu(&arenas_i(mib[2])->astats->astats.retained, ATOMIC_RELAXED),
2837b7eaed25SJason Evans size_t)
2838*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_extent_avail,
2839*c5ad8142SEric van Gyzen atomic_load_zu(&arenas_i(mib[2])->astats->astats.extent_avail,
2840*c5ad8142SEric van Gyzen ATOMIC_RELAXED),
2841*c5ad8142SEric van Gyzen size_t)
2842b7eaed25SJason Evans
2843b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_npurge,
28440ef50b4eSJason Evans ctl_arena_stats_read_u64(
28450ef50b4eSJason Evans &arenas_i(mib[2])->astats->astats.decay_dirty.npurge), uint64_t)
2846b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_nmadvise,
28470ef50b4eSJason Evans ctl_arena_stats_read_u64(
2848b7eaed25SJason Evans &arenas_i(mib[2])->astats->astats.decay_dirty.nmadvise), uint64_t)
2849b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_dirty_purged,
28500ef50b4eSJason Evans ctl_arena_stats_read_u64(
28510ef50b4eSJason Evans &arenas_i(mib[2])->astats->astats.decay_dirty.purged), uint64_t)
2852b7eaed25SJason Evans
2853b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_npurge,
28540ef50b4eSJason Evans ctl_arena_stats_read_u64(
28550ef50b4eSJason Evans &arenas_i(mib[2])->astats->astats.decay_muzzy.npurge), uint64_t)
2856b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_nmadvise,
28570ef50b4eSJason Evans ctl_arena_stats_read_u64(
2858b7eaed25SJason Evans &arenas_i(mib[2])->astats->astats.decay_muzzy.nmadvise), uint64_t)
2859b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_muzzy_purged,
28600ef50b4eSJason Evans ctl_arena_stats_read_u64(
28610ef50b4eSJason Evans &arenas_i(mib[2])->astats->astats.decay_muzzy.purged), uint64_t)
2862b7eaed25SJason Evans
2863b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_base,
2864b7eaed25SJason Evans atomic_load_zu(&arenas_i(mib[2])->astats->astats.base, ATOMIC_RELAXED),
2865b7eaed25SJason Evans size_t)
2866b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_internal,
2867b7eaed25SJason Evans atomic_load_zu(&arenas_i(mib[2])->astats->astats.internal, ATOMIC_RELAXED),
2868b7eaed25SJason Evans size_t)
28690ef50b4eSJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_metadata_thp,
28700ef50b4eSJason Evans atomic_load_zu(&arenas_i(mib[2])->astats->astats.metadata_thp,
28710ef50b4eSJason Evans ATOMIC_RELAXED), size_t)
2872b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_tcache_bytes,
2873b7eaed25SJason Evans atomic_load_zu(&arenas_i(mib[2])->astats->astats.tcache_bytes,
2874b7eaed25SJason Evans ATOMIC_RELAXED), size_t)
2875b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_resident,
2876b7eaed25SJason Evans atomic_load_zu(&arenas_i(mib[2])->astats->astats.resident, ATOMIC_RELAXED),
2877b7eaed25SJason Evans size_t)
2878*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_abandoned_vm,
2879*c5ad8142SEric van Gyzen atomic_load_zu(&arenas_i(mib[2])->astats->astats.abandoned_vm,
2880*c5ad8142SEric van Gyzen ATOMIC_RELAXED), size_t)
2881f921d10fSJason Evans
2882a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_allocated,
2883b7eaed25SJason Evans arenas_i(mib[2])->astats->allocated_small, size_t)
2884a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_nmalloc,
2885b7eaed25SJason Evans arenas_i(mib[2])->astats->nmalloc_small, uint64_t)
2886a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_ndalloc,
2887b7eaed25SJason Evans arenas_i(mib[2])->astats->ndalloc_small, uint64_t)
2888a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_small_nrequests,
2889b7eaed25SJason Evans arenas_i(mib[2])->astats->nrequests_small, uint64_t)
2890*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_small_nfills,
2891*c5ad8142SEric van Gyzen arenas_i(mib[2])->astats->nfills_small, uint64_t)
2892*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_small_nflushes,
2893*c5ad8142SEric van Gyzen arenas_i(mib[2])->astats->nflushes_small, uint64_t)
2894a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_allocated,
2895b7eaed25SJason Evans atomic_load_zu(&arenas_i(mib[2])->astats->astats.allocated_large,
2896b7eaed25SJason Evans ATOMIC_RELAXED), size_t)
2897a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_nmalloc,
28980ef50b4eSJason Evans ctl_arena_stats_read_u64(
28990ef50b4eSJason Evans &arenas_i(mib[2])->astats->astats.nmalloc_large), uint64_t)
2900a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_ndalloc,
29010ef50b4eSJason Evans ctl_arena_stats_read_u64(
29020ef50b4eSJason Evans &arenas_i(mib[2])->astats->astats.ndalloc_large), uint64_t)
2903a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_large_nrequests,
29040ef50b4eSJason Evans ctl_arena_stats_read_u64(
2905*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->astats.nrequests_large), uint64_t)
2906*c5ad8142SEric van Gyzen /*
2907*c5ad8142SEric van Gyzen * Note: "nmalloc_large" here instead of "nfills" in the read. This is
2908*c5ad8142SEric van Gyzen * intentional (large has no batch fill).
2909*c5ad8142SEric van Gyzen */
2910*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_large_nfills,
2911*c5ad8142SEric van Gyzen ctl_arena_stats_read_u64(
2912*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->astats.nmalloc_large), uint64_t)
2913*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_large_nflushes,
2914*c5ad8142SEric van Gyzen ctl_arena_stats_read_u64(
2915*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->astats.nflushes_large), uint64_t)
2916b7eaed25SJason Evans
2917b7eaed25SJason Evans /* Lock profiling related APIs below. */
2918b7eaed25SJason Evans #define RO_MUTEX_CTL_GEN(n, l) \
2919b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_##n##_num_ops, \
2920b7eaed25SJason Evans l.n_lock_ops, uint64_t) \
2921b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_##n##_num_wait, \
2922b7eaed25SJason Evans l.n_wait_times, uint64_t) \
2923b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_##n##_num_spin_acq, \
2924b7eaed25SJason Evans l.n_spin_acquired, uint64_t) \
2925b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_##n##_num_owner_switch, \
2926b7eaed25SJason Evans l.n_owner_switches, uint64_t) \
2927b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_##n##_total_wait_time, \
2928b7eaed25SJason Evans nstime_ns(&l.tot_wait_time), uint64_t) \
2929b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_##n##_max_wait_time, \
2930b7eaed25SJason Evans nstime_ns(&l.max_wait_time), uint64_t) \
2931b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_##n##_max_num_thds, \
2932b7eaed25SJason Evans l.max_n_thds, uint32_t)
2933b7eaed25SJason Evans
2934b7eaed25SJason Evans /* Global mutexes. */
2935b7eaed25SJason Evans #define OP(mtx) \
2936b7eaed25SJason Evans RO_MUTEX_CTL_GEN(mutexes_##mtx, \
2937b7eaed25SJason Evans ctl_stats->mutex_prof_data[global_prof_mutex_##mtx])
2938b7eaed25SJason Evans MUTEX_PROF_GLOBAL_MUTEXES
2939b7eaed25SJason Evans #undef OP
2940b7eaed25SJason Evans
2941b7eaed25SJason Evans /* Per arena mutexes */
2942b7eaed25SJason Evans #define OP(mtx) RO_MUTEX_CTL_GEN(arenas_i_mutexes_##mtx, \
2943b7eaed25SJason Evans arenas_i(mib[2])->astats->astats.mutex_prof_data[arena_prof_mutex_##mtx])
2944b7eaed25SJason Evans MUTEX_PROF_ARENA_MUTEXES
2945b7eaed25SJason Evans #undef OP
2946b7eaed25SJason Evans
2947b7eaed25SJason Evans /* tcache bin mutex */
2948b7eaed25SJason Evans RO_MUTEX_CTL_GEN(arenas_i_bins_j_mutex,
2949b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].mutex_data)
2950b7eaed25SJason Evans #undef RO_MUTEX_CTL_GEN
2951b7eaed25SJason Evans
2952b7eaed25SJason Evans /* Resets all mutex stats, including global, arena and bin mutexes. */
2953b7eaed25SJason Evans static int
stats_mutexes_reset_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)2954*c5ad8142SEric van Gyzen stats_mutexes_reset_ctl(tsd_t *tsd, const size_t *mib,
2955*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp,
2956*c5ad8142SEric van Gyzen void *newp, size_t newlen) {
2957b7eaed25SJason Evans if (!config_stats) {
2958b7eaed25SJason Evans return ENOENT;
2959b7eaed25SJason Evans }
2960b7eaed25SJason Evans
2961b7eaed25SJason Evans tsdn_t *tsdn = tsd_tsdn(tsd);
2962b7eaed25SJason Evans
2963b7eaed25SJason Evans #define MUTEX_PROF_RESET(mtx) \
2964b7eaed25SJason Evans malloc_mutex_lock(tsdn, &mtx); \
2965b7eaed25SJason Evans malloc_mutex_prof_data_reset(tsdn, &mtx); \
2966b7eaed25SJason Evans malloc_mutex_unlock(tsdn, &mtx);
2967b7eaed25SJason Evans
2968b7eaed25SJason Evans /* Global mutexes: ctl and prof. */
2969b7eaed25SJason Evans MUTEX_PROF_RESET(ctl_mtx);
2970b7eaed25SJason Evans if (have_background_thread) {
2971b7eaed25SJason Evans MUTEX_PROF_RESET(background_thread_lock);
2972b7eaed25SJason Evans }
2973b7eaed25SJason Evans if (config_prof && opt_prof) {
2974b7eaed25SJason Evans MUTEX_PROF_RESET(bt2gctx_mtx);
2975b7eaed25SJason Evans }
2976b7eaed25SJason Evans
2977b7eaed25SJason Evans
2978b7eaed25SJason Evans /* Per arena mutexes. */
2979b7eaed25SJason Evans unsigned n = narenas_total_get();
2980b7eaed25SJason Evans
2981b7eaed25SJason Evans for (unsigned i = 0; i < n; i++) {
2982b7eaed25SJason Evans arena_t *arena = arena_get(tsdn, i, false);
2983b7eaed25SJason Evans if (!arena) {
2984b7eaed25SJason Evans continue;
2985b7eaed25SJason Evans }
2986b7eaed25SJason Evans MUTEX_PROF_RESET(arena->large_mtx);
2987b7eaed25SJason Evans MUTEX_PROF_RESET(arena->extent_avail_mtx);
2988b7eaed25SJason Evans MUTEX_PROF_RESET(arena->extents_dirty.mtx);
2989b7eaed25SJason Evans MUTEX_PROF_RESET(arena->extents_muzzy.mtx);
2990b7eaed25SJason Evans MUTEX_PROF_RESET(arena->extents_retained.mtx);
2991b7eaed25SJason Evans MUTEX_PROF_RESET(arena->decay_dirty.mtx);
2992b7eaed25SJason Evans MUTEX_PROF_RESET(arena->decay_muzzy.mtx);
2993b7eaed25SJason Evans MUTEX_PROF_RESET(arena->tcache_ql_mtx);
2994b7eaed25SJason Evans MUTEX_PROF_RESET(arena->base->mtx);
2995b7eaed25SJason Evans
2996*c5ad8142SEric van Gyzen for (szind_t i = 0; i < SC_NBINS; i++) {
2997*c5ad8142SEric van Gyzen for (unsigned j = 0; j < bin_infos[i].n_shards; j++) {
2998*c5ad8142SEric van Gyzen bin_t *bin = &arena->bins[i].bin_shards[j];
2999b7eaed25SJason Evans MUTEX_PROF_RESET(bin->lock);
3000b7eaed25SJason Evans }
3001b7eaed25SJason Evans }
3002*c5ad8142SEric van Gyzen }
3003b7eaed25SJason Evans #undef MUTEX_PROF_RESET
3004b7eaed25SJason Evans return 0;
3005b7eaed25SJason Evans }
3006a4bd5210SJason Evans
3007a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nmalloc,
3008b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].nmalloc, uint64_t)
3009a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_ndalloc,
3010b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].ndalloc, uint64_t)
3011a4bd5210SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nrequests,
3012b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].nrequests, uint64_t)
3013d0e79aa3SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curregs,
3014b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].curregs, size_t)
3015b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nfills,
3016b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].nfills, uint64_t)
3017b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nflushes,
3018b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].nflushes, uint64_t)
3019b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nslabs,
3020b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].nslabs, uint64_t)
3021b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nreslabs,
3022b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].reslabs, uint64_t)
3023b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_curslabs,
3024b7eaed25SJason Evans arenas_i(mib[2])->astats->bstats[mib[4]].curslabs, size_t)
3025*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_bins_j_nonfull_slabs,
3026*c5ad8142SEric van Gyzen arenas_i(mib[2])->astats->bstats[mib[4]].nonfull_slabs, size_t)
3027a4bd5210SJason Evans
302882872ac0SJason Evans static const ctl_named_node_t *
stats_arenas_i_bins_j_index(tsdn_t * tsdn,const size_t * mib,size_t miblen,size_t j)3029*c5ad8142SEric van Gyzen stats_arenas_i_bins_j_index(tsdn_t *tsdn, const size_t *mib,
3030*c5ad8142SEric van Gyzen size_t miblen, size_t j) {
3031*c5ad8142SEric van Gyzen if (j > SC_NBINS) {
3032b7eaed25SJason Evans return NULL;
3033b7eaed25SJason Evans }
3034b7eaed25SJason Evans return super_stats_arenas_i_bins_j_node;
3035a4bd5210SJason Evans }
3036a4bd5210SJason Evans
3037b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_nmalloc,
30380ef50b4eSJason Evans ctl_arena_stats_read_u64(
30390ef50b4eSJason Evans &arenas_i(mib[2])->astats->lstats[mib[4]].nmalloc), uint64_t)
3040b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_ndalloc,
30410ef50b4eSJason Evans ctl_arena_stats_read_u64(
30420ef50b4eSJason Evans &arenas_i(mib[2])->astats->lstats[mib[4]].ndalloc), uint64_t)
3043b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_nrequests,
30440ef50b4eSJason Evans ctl_arena_stats_read_u64(
30450ef50b4eSJason Evans &arenas_i(mib[2])->astats->lstats[mib[4]].nrequests), uint64_t)
3046b7eaed25SJason Evans CTL_RO_CGEN(config_stats, stats_arenas_i_lextents_j_curlextents,
3047b7eaed25SJason Evans arenas_i(mib[2])->astats->lstats[mib[4]].curlextents, size_t)
3048d0e79aa3SJason Evans
3049d0e79aa3SJason Evans static const ctl_named_node_t *
stats_arenas_i_lextents_j_index(tsdn_t * tsdn,const size_t * mib,size_t miblen,size_t j)3050*c5ad8142SEric van Gyzen stats_arenas_i_lextents_j_index(tsdn_t *tsdn, const size_t *mib,
3051*c5ad8142SEric van Gyzen size_t miblen, size_t j) {
3052*c5ad8142SEric van Gyzen if (j > SC_NSIZES - SC_NBINS) {
3053b7eaed25SJason Evans return NULL;
3054b7eaed25SJason Evans }
3055b7eaed25SJason Evans return super_stats_arenas_i_lextents_j_node;
3056d0e79aa3SJason Evans }
3057d0e79aa3SJason Evans
3058*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_ndirty,
3059*c5ad8142SEric van Gyzen atomic_load_zu(
3060*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->estats[mib[4]].ndirty,
3061*c5ad8142SEric van Gyzen ATOMIC_RELAXED), size_t);
3062*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_nmuzzy,
3063*c5ad8142SEric van Gyzen atomic_load_zu(
3064*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->estats[mib[4]].nmuzzy,
3065*c5ad8142SEric van Gyzen ATOMIC_RELAXED), size_t);
3066*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_nretained,
3067*c5ad8142SEric van Gyzen atomic_load_zu(
3068*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->estats[mib[4]].nretained,
3069*c5ad8142SEric van Gyzen ATOMIC_RELAXED), size_t);
3070*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_dirty_bytes,
3071*c5ad8142SEric van Gyzen atomic_load_zu(
3072*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->estats[mib[4]].dirty_bytes,
3073*c5ad8142SEric van Gyzen ATOMIC_RELAXED), size_t);
3074*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_muzzy_bytes,
3075*c5ad8142SEric van Gyzen atomic_load_zu(
3076*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->estats[mib[4]].muzzy_bytes,
3077*c5ad8142SEric van Gyzen ATOMIC_RELAXED), size_t);
3078*c5ad8142SEric van Gyzen CTL_RO_CGEN(config_stats, stats_arenas_i_extents_j_retained_bytes,
3079*c5ad8142SEric van Gyzen atomic_load_zu(
3080*c5ad8142SEric van Gyzen &arenas_i(mib[2])->astats->estats[mib[4]].retained_bytes,
3081*c5ad8142SEric van Gyzen ATOMIC_RELAXED), size_t);
3082*c5ad8142SEric van Gyzen
308382872ac0SJason Evans static const ctl_named_node_t *
stats_arenas_i_extents_j_index(tsdn_t * tsdn,const size_t * mib,size_t miblen,size_t j)3084*c5ad8142SEric van Gyzen stats_arenas_i_extents_j_index(tsdn_t *tsdn, const size_t *mib,
3085*c5ad8142SEric van Gyzen size_t miblen, size_t j) {
3086*c5ad8142SEric van Gyzen if (j >= SC_NPSIZES) {
3087*c5ad8142SEric van Gyzen return NULL;
3088*c5ad8142SEric van Gyzen }
3089*c5ad8142SEric van Gyzen return super_stats_arenas_i_extents_j_node;
3090*c5ad8142SEric van Gyzen }
3091*c5ad8142SEric van Gyzen
3092*c5ad8142SEric van Gyzen static bool
ctl_arenas_i_verify(size_t i)3093*c5ad8142SEric van Gyzen ctl_arenas_i_verify(size_t i) {
3094*c5ad8142SEric van Gyzen size_t a = arenas_i2a_impl(i, true, true);
3095*c5ad8142SEric van Gyzen if (a == UINT_MAX || !ctl_arenas->arenas[a]->initialized) {
3096*c5ad8142SEric van Gyzen return true;
3097*c5ad8142SEric van Gyzen }
3098*c5ad8142SEric van Gyzen
3099*c5ad8142SEric van Gyzen return false;
3100*c5ad8142SEric van Gyzen }
3101*c5ad8142SEric van Gyzen
3102*c5ad8142SEric van Gyzen static const ctl_named_node_t *
stats_arenas_i_index(tsdn_t * tsdn,const size_t * mib,size_t miblen,size_t i)3103*c5ad8142SEric van Gyzen stats_arenas_i_index(tsdn_t *tsdn, const size_t *mib,
3104*c5ad8142SEric van Gyzen size_t miblen, size_t i) {
3105e722f8f8SJason Evans const ctl_named_node_t *ret;
3106a4bd5210SJason Evans
31071f0a49e8SJason Evans malloc_mutex_lock(tsdn, &ctl_mtx);
3108*c5ad8142SEric van Gyzen if (ctl_arenas_i_verify(i)) {
3109a4bd5210SJason Evans ret = NULL;
3110a4bd5210SJason Evans goto label_return;
3111a4bd5210SJason Evans }
3112a4bd5210SJason Evans
3113a4bd5210SJason Evans ret = super_stats_arenas_i_node;
3114a4bd5210SJason Evans label_return:
31151f0a49e8SJason Evans malloc_mutex_unlock(tsdn, &ctl_mtx);
3116b7eaed25SJason Evans return ret;
3117a4bd5210SJason Evans }
3118*c5ad8142SEric van Gyzen
3119*c5ad8142SEric van Gyzen static int
experimental_hooks_install_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)3120*c5ad8142SEric van Gyzen experimental_hooks_install_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
3121*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
3122*c5ad8142SEric van Gyzen int ret;
3123*c5ad8142SEric van Gyzen if (oldp == NULL || oldlenp == NULL|| newp == NULL) {
3124*c5ad8142SEric van Gyzen ret = EINVAL;
3125*c5ad8142SEric van Gyzen goto label_return;
3126*c5ad8142SEric van Gyzen }
3127*c5ad8142SEric van Gyzen /*
3128*c5ad8142SEric van Gyzen * Note: this is a *private* struct. This is an experimental interface;
3129*c5ad8142SEric van Gyzen * forcing the user to know the jemalloc internals well enough to
3130*c5ad8142SEric van Gyzen * extract the ABI hopefully ensures nobody gets too comfortable with
3131*c5ad8142SEric van Gyzen * this API, which can change at a moment's notice.
3132*c5ad8142SEric van Gyzen */
3133*c5ad8142SEric van Gyzen hooks_t hooks;
3134*c5ad8142SEric van Gyzen WRITE(hooks, hooks_t);
3135*c5ad8142SEric van Gyzen void *handle = hook_install(tsd_tsdn(tsd), &hooks);
3136*c5ad8142SEric van Gyzen if (handle == NULL) {
3137*c5ad8142SEric van Gyzen ret = EAGAIN;
3138*c5ad8142SEric van Gyzen goto label_return;
3139*c5ad8142SEric van Gyzen }
3140*c5ad8142SEric van Gyzen READ(handle, void *);
3141*c5ad8142SEric van Gyzen
3142*c5ad8142SEric van Gyzen ret = 0;
3143*c5ad8142SEric van Gyzen label_return:
3144*c5ad8142SEric van Gyzen return ret;
3145*c5ad8142SEric van Gyzen }
3146*c5ad8142SEric van Gyzen
3147*c5ad8142SEric van Gyzen static int
experimental_hooks_remove_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)3148*c5ad8142SEric van Gyzen experimental_hooks_remove_ctl(tsd_t *tsd, const size_t *mib, size_t miblen,
3149*c5ad8142SEric van Gyzen void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
3150*c5ad8142SEric van Gyzen int ret;
3151*c5ad8142SEric van Gyzen WRITEONLY();
3152*c5ad8142SEric van Gyzen void *handle = NULL;
3153*c5ad8142SEric van Gyzen WRITE(handle, void *);
3154*c5ad8142SEric van Gyzen if (handle == NULL) {
3155*c5ad8142SEric van Gyzen ret = EINVAL;
3156*c5ad8142SEric van Gyzen goto label_return;
3157*c5ad8142SEric van Gyzen }
3158*c5ad8142SEric van Gyzen hook_remove(tsd_tsdn(tsd), handle);
3159*c5ad8142SEric van Gyzen ret = 0;
3160*c5ad8142SEric van Gyzen label_return:
3161*c5ad8142SEric van Gyzen return ret;
3162*c5ad8142SEric van Gyzen }
3163*c5ad8142SEric van Gyzen
3164*c5ad8142SEric van Gyzen /*
3165*c5ad8142SEric van Gyzen * Output six memory utilization entries for an input pointer, the first one of
3166*c5ad8142SEric van Gyzen * type (void *) and the remaining five of type size_t, describing the following
3167*c5ad8142SEric van Gyzen * (in the same order):
3168*c5ad8142SEric van Gyzen *
3169*c5ad8142SEric van Gyzen * (a) memory address of the extent a potential reallocation would go into,
3170*c5ad8142SEric van Gyzen * == the five fields below describe about the extent the pointer resides in ==
3171*c5ad8142SEric van Gyzen * (b) number of free regions in the extent,
3172*c5ad8142SEric van Gyzen * (c) number of regions in the extent,
3173*c5ad8142SEric van Gyzen * (d) size of the extent in terms of bytes,
3174*c5ad8142SEric van Gyzen * (e) total number of free regions in the bin the extent belongs to, and
3175*c5ad8142SEric van Gyzen * (f) total number of regions in the bin the extent belongs to.
3176*c5ad8142SEric van Gyzen *
3177*c5ad8142SEric van Gyzen * Note that "(e)" and "(f)" are only available when stats are enabled;
3178*c5ad8142SEric van Gyzen * otherwise their values are undefined.
3179*c5ad8142SEric van Gyzen *
3180*c5ad8142SEric van Gyzen * This API is mainly intended for small class allocations, where extents are
3181*c5ad8142SEric van Gyzen * used as slab.
3182*c5ad8142SEric van Gyzen *
3183*c5ad8142SEric van Gyzen * In case of large class allocations, "(a)" will be NULL, and "(e)" and "(f)"
3184*c5ad8142SEric van Gyzen * will be zero (if stats are enabled; otherwise undefined). The other three
3185*c5ad8142SEric van Gyzen * fields will be properly set though the values are trivial: "(b)" will be 0,
3186*c5ad8142SEric van Gyzen * "(c)" will be 1, and "(d)" will be the usable size.
3187*c5ad8142SEric van Gyzen *
3188*c5ad8142SEric van Gyzen * The input pointer and size are respectively passed in by newp and newlen,
3189*c5ad8142SEric van Gyzen * and the output fields and size are respectively oldp and *oldlenp.
3190*c5ad8142SEric van Gyzen *
3191*c5ad8142SEric van Gyzen * It can be beneficial to define the following macros to make it easier to
3192*c5ad8142SEric van Gyzen * access the output:
3193*c5ad8142SEric van Gyzen *
3194*c5ad8142SEric van Gyzen * #define SLABCUR_READ(out) (*(void **)out)
3195*c5ad8142SEric van Gyzen * #define COUNTS(out) ((size_t *)((void **)out + 1))
3196*c5ad8142SEric van Gyzen * #define NFREE_READ(out) COUNTS(out)[0]
3197*c5ad8142SEric van Gyzen * #define NREGS_READ(out) COUNTS(out)[1]
3198*c5ad8142SEric van Gyzen * #define SIZE_READ(out) COUNTS(out)[2]
3199*c5ad8142SEric van Gyzen * #define BIN_NFREE_READ(out) COUNTS(out)[3]
3200*c5ad8142SEric van Gyzen * #define BIN_NREGS_READ(out) COUNTS(out)[4]
3201*c5ad8142SEric van Gyzen *
3202*c5ad8142SEric van Gyzen * and then write e.g. NFREE_READ(oldp) to fetch the output. See the unit test
3203*c5ad8142SEric van Gyzen * test_query in test/unit/extent_util.c for an example.
3204*c5ad8142SEric van Gyzen *
3205*c5ad8142SEric van Gyzen * For a typical defragmentation workflow making use of this API for
3206*c5ad8142SEric van Gyzen * understanding the fragmentation level, please refer to the comment for
3207*c5ad8142SEric van Gyzen * experimental_utilization_batch_query_ctl.
3208*c5ad8142SEric van Gyzen *
3209*c5ad8142SEric van Gyzen * It's up to the application how to determine the significance of
3210*c5ad8142SEric van Gyzen * fragmentation relying on the outputs returned. Possible choices are:
3211*c5ad8142SEric van Gyzen *
3212*c5ad8142SEric van Gyzen * (a) if extent utilization ratio is below certain threshold,
3213*c5ad8142SEric van Gyzen * (b) if extent memory consumption is above certain threshold,
3214*c5ad8142SEric van Gyzen * (c) if extent utilization ratio is significantly below bin utilization ratio,
3215*c5ad8142SEric van Gyzen * (d) if input pointer deviates a lot from potential reallocation address, or
3216*c5ad8142SEric van Gyzen * (e) some selection/combination of the above.
3217*c5ad8142SEric van Gyzen *
3218*c5ad8142SEric van Gyzen * The caller needs to make sure that the input/output arguments are valid,
3219*c5ad8142SEric van Gyzen * in particular, that the size of the output is correct, i.e.:
3220*c5ad8142SEric van Gyzen *
3221*c5ad8142SEric van Gyzen * *oldlenp = sizeof(void *) + sizeof(size_t) * 5
3222*c5ad8142SEric van Gyzen *
3223*c5ad8142SEric van Gyzen * Otherwise, the function immediately returns EINVAL without touching anything.
3224*c5ad8142SEric van Gyzen *
3225*c5ad8142SEric van Gyzen * In the rare case where there's no associated extent found for the input
3226*c5ad8142SEric van Gyzen * pointer, the function zeros out all output fields and return. Please refer
3227*c5ad8142SEric van Gyzen * to the comment for experimental_utilization_batch_query_ctl to understand the
3228*c5ad8142SEric van Gyzen * motivation from C++.
3229*c5ad8142SEric van Gyzen */
3230*c5ad8142SEric van Gyzen static int
experimental_utilization_query_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)3231*c5ad8142SEric van Gyzen experimental_utilization_query_ctl(tsd_t *tsd, const size_t *mib,
3232*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
3233*c5ad8142SEric van Gyzen int ret;
3234*c5ad8142SEric van Gyzen
3235*c5ad8142SEric van Gyzen assert(sizeof(extent_util_stats_verbose_t)
3236*c5ad8142SEric van Gyzen == sizeof(void *) + sizeof(size_t) * 5);
3237*c5ad8142SEric van Gyzen
3238*c5ad8142SEric van Gyzen if (oldp == NULL || oldlenp == NULL
3239*c5ad8142SEric van Gyzen || *oldlenp != sizeof(extent_util_stats_verbose_t)
3240*c5ad8142SEric van Gyzen || newp == NULL) {
3241*c5ad8142SEric van Gyzen ret = EINVAL;
3242*c5ad8142SEric van Gyzen goto label_return;
3243*c5ad8142SEric van Gyzen }
3244*c5ad8142SEric van Gyzen
3245*c5ad8142SEric van Gyzen void *ptr = NULL;
3246*c5ad8142SEric van Gyzen WRITE(ptr, void *);
3247*c5ad8142SEric van Gyzen extent_util_stats_verbose_t *util_stats
3248*c5ad8142SEric van Gyzen = (extent_util_stats_verbose_t *)oldp;
3249*c5ad8142SEric van Gyzen extent_util_stats_verbose_get(tsd_tsdn(tsd), ptr,
3250*c5ad8142SEric van Gyzen &util_stats->nfree, &util_stats->nregs, &util_stats->size,
3251*c5ad8142SEric van Gyzen &util_stats->bin_nfree, &util_stats->bin_nregs,
3252*c5ad8142SEric van Gyzen &util_stats->slabcur_addr);
3253*c5ad8142SEric van Gyzen ret = 0;
3254*c5ad8142SEric van Gyzen
3255*c5ad8142SEric van Gyzen label_return:
3256*c5ad8142SEric van Gyzen return ret;
3257*c5ad8142SEric van Gyzen }
3258*c5ad8142SEric van Gyzen
3259*c5ad8142SEric van Gyzen /*
3260*c5ad8142SEric van Gyzen * Given an input array of pointers, output three memory utilization entries of
3261*c5ad8142SEric van Gyzen * type size_t for each input pointer about the extent it resides in:
3262*c5ad8142SEric van Gyzen *
3263*c5ad8142SEric van Gyzen * (a) number of free regions in the extent,
3264*c5ad8142SEric van Gyzen * (b) number of regions in the extent, and
3265*c5ad8142SEric van Gyzen * (c) size of the extent in terms of bytes.
3266*c5ad8142SEric van Gyzen *
3267*c5ad8142SEric van Gyzen * This API is mainly intended for small class allocations, where extents are
3268*c5ad8142SEric van Gyzen * used as slab. In case of large class allocations, the outputs are trivial:
3269*c5ad8142SEric van Gyzen * "(a)" will be 0, "(b)" will be 1, and "(c)" will be the usable size.
3270*c5ad8142SEric van Gyzen *
3271*c5ad8142SEric van Gyzen * Note that multiple input pointers may reside on a same extent so the output
3272*c5ad8142SEric van Gyzen * fields may contain duplicates.
3273*c5ad8142SEric van Gyzen *
3274*c5ad8142SEric van Gyzen * The format of the input/output looks like:
3275*c5ad8142SEric van Gyzen *
3276*c5ad8142SEric van Gyzen * input[0]: 1st_pointer_to_query | output[0]: 1st_extent_n_free_regions
3277*c5ad8142SEric van Gyzen * | output[1]: 1st_extent_n_regions
3278*c5ad8142SEric van Gyzen * | output[2]: 1st_extent_size
3279*c5ad8142SEric van Gyzen * input[1]: 2nd_pointer_to_query | output[3]: 2nd_extent_n_free_regions
3280*c5ad8142SEric van Gyzen * | output[4]: 2nd_extent_n_regions
3281*c5ad8142SEric van Gyzen * | output[5]: 2nd_extent_size
3282*c5ad8142SEric van Gyzen * ... | ...
3283*c5ad8142SEric van Gyzen *
3284*c5ad8142SEric van Gyzen * The input array and size are respectively passed in by newp and newlen, and
3285*c5ad8142SEric van Gyzen * the output array and size are respectively oldp and *oldlenp.
3286*c5ad8142SEric van Gyzen *
3287*c5ad8142SEric van Gyzen * It can be beneficial to define the following macros to make it easier to
3288*c5ad8142SEric van Gyzen * access the output:
3289*c5ad8142SEric van Gyzen *
3290*c5ad8142SEric van Gyzen * #define NFREE_READ(out, i) out[(i) * 3]
3291*c5ad8142SEric van Gyzen * #define NREGS_READ(out, i) out[(i) * 3 + 1]
3292*c5ad8142SEric van Gyzen * #define SIZE_READ(out, i) out[(i) * 3 + 2]
3293*c5ad8142SEric van Gyzen *
3294*c5ad8142SEric van Gyzen * and then write e.g. NFREE_READ(oldp, i) to fetch the output. See the unit
3295*c5ad8142SEric van Gyzen * test test_batch in test/unit/extent_util.c for a concrete example.
3296*c5ad8142SEric van Gyzen *
3297*c5ad8142SEric van Gyzen * A typical workflow would be composed of the following steps:
3298*c5ad8142SEric van Gyzen *
3299*c5ad8142SEric van Gyzen * (1) flush tcache: mallctl("thread.tcache.flush", ...)
3300*c5ad8142SEric van Gyzen * (2) initialize input array of pointers to query fragmentation
3301*c5ad8142SEric van Gyzen * (3) allocate output array to hold utilization statistics
3302*c5ad8142SEric van Gyzen * (4) query utilization: mallctl("experimental.utilization.batch_query", ...)
3303*c5ad8142SEric van Gyzen * (5) (optional) decide if it's worthwhile to defragment; otherwise stop here
3304*c5ad8142SEric van Gyzen * (6) disable tcache: mallctl("thread.tcache.enabled", ...)
3305*c5ad8142SEric van Gyzen * (7) defragment allocations with significant fragmentation, e.g.:
3306*c5ad8142SEric van Gyzen * for each allocation {
3307*c5ad8142SEric van Gyzen * if it's fragmented {
3308*c5ad8142SEric van Gyzen * malloc(...);
3309*c5ad8142SEric van Gyzen * memcpy(...);
3310*c5ad8142SEric van Gyzen * free(...);
3311*c5ad8142SEric van Gyzen * }
3312*c5ad8142SEric van Gyzen * }
3313*c5ad8142SEric van Gyzen * (8) enable tcache: mallctl("thread.tcache.enabled", ...)
3314*c5ad8142SEric van Gyzen *
3315*c5ad8142SEric van Gyzen * The application can determine the significance of fragmentation themselves
3316*c5ad8142SEric van Gyzen * relying on the statistics returned, both at the overall level i.e. step "(5)"
3317*c5ad8142SEric van Gyzen * and at individual allocation level i.e. within step "(7)". Possible choices
3318*c5ad8142SEric van Gyzen * are:
3319*c5ad8142SEric van Gyzen *
3320*c5ad8142SEric van Gyzen * (a) whether memory utilization ratio is below certain threshold,
3321*c5ad8142SEric van Gyzen * (b) whether memory consumption is above certain threshold, or
3322*c5ad8142SEric van Gyzen * (c) some combination of the two.
3323*c5ad8142SEric van Gyzen *
3324*c5ad8142SEric van Gyzen * The caller needs to make sure that the input/output arrays are valid and
3325*c5ad8142SEric van Gyzen * their sizes are proper as well as matched, meaning:
3326*c5ad8142SEric van Gyzen *
3327*c5ad8142SEric van Gyzen * (a) newlen = n_pointers * sizeof(const void *)
3328*c5ad8142SEric van Gyzen * (b) *oldlenp = n_pointers * sizeof(size_t) * 3
3329*c5ad8142SEric van Gyzen * (c) n_pointers > 0
3330*c5ad8142SEric van Gyzen *
3331*c5ad8142SEric van Gyzen * Otherwise, the function immediately returns EINVAL without touching anything.
3332*c5ad8142SEric van Gyzen *
3333*c5ad8142SEric van Gyzen * In the rare case where there's no associated extent found for some pointers,
3334*c5ad8142SEric van Gyzen * rather than immediately terminating the computation and raising an error,
3335*c5ad8142SEric van Gyzen * the function simply zeros out the corresponding output fields and continues
3336*c5ad8142SEric van Gyzen * the computation until all input pointers are handled. The motivations of
3337*c5ad8142SEric van Gyzen * such a design are as follows:
3338*c5ad8142SEric van Gyzen *
3339*c5ad8142SEric van Gyzen * (a) The function always either processes nothing or processes everything, and
3340*c5ad8142SEric van Gyzen * never leaves the output half touched and half untouched.
3341*c5ad8142SEric van Gyzen *
3342*c5ad8142SEric van Gyzen * (b) It facilitates usage needs especially common in C++. A vast variety of
3343*c5ad8142SEric van Gyzen * C++ objects are instantiated with multiple dynamic memory allocations. For
3344*c5ad8142SEric van Gyzen * example, std::string and std::vector typically use at least two allocations,
3345*c5ad8142SEric van Gyzen * one for the metadata and one for the actual content. Other types may use
3346*c5ad8142SEric van Gyzen * even more allocations. When inquiring about utilization statistics, the
3347*c5ad8142SEric van Gyzen * caller often wants to examine into all such allocations, especially internal
3348*c5ad8142SEric van Gyzen * one(s), rather than just the topmost one. The issue comes when some
3349*c5ad8142SEric van Gyzen * implementations do certain optimizations to reduce/aggregate some internal
3350*c5ad8142SEric van Gyzen * allocations, e.g. putting short strings directly into the metadata, and such
3351*c5ad8142SEric van Gyzen * decisions are not known to the caller. Therefore, we permit pointers to
3352*c5ad8142SEric van Gyzen * memory usages that may not be returned by previous malloc calls, and we
3353*c5ad8142SEric van Gyzen * provide the caller a convenient way to identify such cases.
3354*c5ad8142SEric van Gyzen */
3355*c5ad8142SEric van Gyzen static int
experimental_utilization_batch_query_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)3356*c5ad8142SEric van Gyzen experimental_utilization_batch_query_ctl(tsd_t *tsd, const size_t *mib,
3357*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
3358*c5ad8142SEric van Gyzen int ret;
3359*c5ad8142SEric van Gyzen
3360*c5ad8142SEric van Gyzen assert(sizeof(extent_util_stats_t) == sizeof(size_t) * 3);
3361*c5ad8142SEric van Gyzen
3362*c5ad8142SEric van Gyzen const size_t len = newlen / sizeof(const void *);
3363*c5ad8142SEric van Gyzen if (oldp == NULL || oldlenp == NULL || newp == NULL || newlen == 0
3364*c5ad8142SEric van Gyzen || newlen != len * sizeof(const void *)
3365*c5ad8142SEric van Gyzen || *oldlenp != len * sizeof(extent_util_stats_t)) {
3366*c5ad8142SEric van Gyzen ret = EINVAL;
3367*c5ad8142SEric van Gyzen goto label_return;
3368*c5ad8142SEric van Gyzen }
3369*c5ad8142SEric van Gyzen
3370*c5ad8142SEric van Gyzen void **ptrs = (void **)newp;
3371*c5ad8142SEric van Gyzen extent_util_stats_t *util_stats = (extent_util_stats_t *)oldp;
3372*c5ad8142SEric van Gyzen size_t i;
3373*c5ad8142SEric van Gyzen for (i = 0; i < len; ++i) {
3374*c5ad8142SEric van Gyzen extent_util_stats_get(tsd_tsdn(tsd), ptrs[i],
3375*c5ad8142SEric van Gyzen &util_stats[i].nfree, &util_stats[i].nregs,
3376*c5ad8142SEric van Gyzen &util_stats[i].size);
3377*c5ad8142SEric van Gyzen }
3378*c5ad8142SEric van Gyzen ret = 0;
3379*c5ad8142SEric van Gyzen
3380*c5ad8142SEric van Gyzen label_return:
3381*c5ad8142SEric van Gyzen return ret;
3382*c5ad8142SEric van Gyzen }
3383*c5ad8142SEric van Gyzen
3384*c5ad8142SEric van Gyzen static const ctl_named_node_t *
experimental_arenas_i_index(tsdn_t * tsdn,const size_t * mib,size_t miblen,size_t i)3385*c5ad8142SEric van Gyzen experimental_arenas_i_index(tsdn_t *tsdn, const size_t *mib,
3386*c5ad8142SEric van Gyzen size_t miblen, size_t i) {
3387*c5ad8142SEric van Gyzen const ctl_named_node_t *ret;
3388*c5ad8142SEric van Gyzen
3389*c5ad8142SEric van Gyzen malloc_mutex_lock(tsdn, &ctl_mtx);
3390*c5ad8142SEric van Gyzen if (ctl_arenas_i_verify(i)) {
3391*c5ad8142SEric van Gyzen ret = NULL;
3392*c5ad8142SEric van Gyzen goto label_return;
3393*c5ad8142SEric van Gyzen }
3394*c5ad8142SEric van Gyzen ret = super_experimental_arenas_i_node;
3395*c5ad8142SEric van Gyzen label_return:
3396*c5ad8142SEric van Gyzen malloc_mutex_unlock(tsdn, &ctl_mtx);
3397*c5ad8142SEric van Gyzen return ret;
3398*c5ad8142SEric van Gyzen }
3399*c5ad8142SEric van Gyzen
3400*c5ad8142SEric van Gyzen static int
experimental_arenas_i_pactivep_ctl(tsd_t * tsd,const size_t * mib,size_t miblen,void * oldp,size_t * oldlenp,void * newp,size_t newlen)3401*c5ad8142SEric van Gyzen experimental_arenas_i_pactivep_ctl(tsd_t *tsd, const size_t *mib,
3402*c5ad8142SEric van Gyzen size_t miblen, void *oldp, size_t *oldlenp, void *newp, size_t newlen) {
3403*c5ad8142SEric van Gyzen if (!config_stats) {
3404*c5ad8142SEric van Gyzen return ENOENT;
3405*c5ad8142SEric van Gyzen }
3406*c5ad8142SEric van Gyzen if (oldp == NULL || oldlenp == NULL || *oldlenp != sizeof(size_t *)) {
3407*c5ad8142SEric van Gyzen return EINVAL;
3408*c5ad8142SEric van Gyzen }
3409*c5ad8142SEric van Gyzen
3410*c5ad8142SEric van Gyzen unsigned arena_ind;
3411*c5ad8142SEric van Gyzen arena_t *arena;
3412*c5ad8142SEric van Gyzen int ret;
3413*c5ad8142SEric van Gyzen size_t *pactivep;
3414*c5ad8142SEric van Gyzen
3415*c5ad8142SEric van Gyzen malloc_mutex_lock(tsd_tsdn(tsd), &ctl_mtx);
3416*c5ad8142SEric van Gyzen READONLY();
3417*c5ad8142SEric van Gyzen MIB_UNSIGNED(arena_ind, 2);
3418*c5ad8142SEric van Gyzen if (arena_ind < narenas_total_get() && (arena =
3419*c5ad8142SEric van Gyzen arena_get(tsd_tsdn(tsd), arena_ind, false)) != NULL) {
3420*c5ad8142SEric van Gyzen #if defined(JEMALLOC_GCC_ATOMIC_ATOMICS) || \
3421*c5ad8142SEric van Gyzen defined(JEMALLOC_GCC_SYNC_ATOMICS) || defined(_MSC_VER)
3422*c5ad8142SEric van Gyzen /* Expose the underlying counter for fast read. */
3423*c5ad8142SEric van Gyzen pactivep = (size_t *)&(arena->nactive.repr);
3424*c5ad8142SEric van Gyzen READ(pactivep, size_t *);
3425*c5ad8142SEric van Gyzen ret = 0;
3426*c5ad8142SEric van Gyzen #else
3427*c5ad8142SEric van Gyzen ret = EFAULT;
3428*c5ad8142SEric van Gyzen #endif
3429*c5ad8142SEric van Gyzen } else {
3430*c5ad8142SEric van Gyzen ret = EFAULT;
3431*c5ad8142SEric van Gyzen }
3432*c5ad8142SEric van Gyzen label_return:
3433*c5ad8142SEric van Gyzen malloc_mutex_unlock(tsd_tsdn(tsd), &ctl_mtx);
3434*c5ad8142SEric van Gyzen return ret;
3435*c5ad8142SEric van Gyzen }
3436