xref: /freebsd/contrib/jemalloc/src/pa_extra.c (revision c43cad87172039ccf38172129c79755ea79e6102)
1*c43cad87SWarner Losh #include "jemalloc/internal/jemalloc_preamble.h"
2*c43cad87SWarner Losh #include "jemalloc/internal/jemalloc_internal_includes.h"
3*c43cad87SWarner Losh 
4*c43cad87SWarner Losh /*
5*c43cad87SWarner Losh  * This file is logically part of the PA module.  While pa.c contains the core
6*c43cad87SWarner Losh  * allocator functionality, this file contains boring integration functionality;
7*c43cad87SWarner Losh  * things like the pre- and post- fork handlers, and stats merging for CTL
8*c43cad87SWarner Losh  * refreshes.
9*c43cad87SWarner Losh  */
10*c43cad87SWarner Losh 
11*c43cad87SWarner Losh void
12*c43cad87SWarner Losh pa_shard_prefork0(tsdn_t *tsdn, pa_shard_t *shard) {
13*c43cad87SWarner Losh 	malloc_mutex_prefork(tsdn, &shard->pac.decay_dirty.mtx);
14*c43cad87SWarner Losh 	malloc_mutex_prefork(tsdn, &shard->pac.decay_muzzy.mtx);
15*c43cad87SWarner Losh }
16*c43cad87SWarner Losh 
17*c43cad87SWarner Losh void
18*c43cad87SWarner Losh pa_shard_prefork2(tsdn_t *tsdn, pa_shard_t *shard) {
19*c43cad87SWarner Losh 	if (shard->ever_used_hpa) {
20*c43cad87SWarner Losh 		sec_prefork2(tsdn, &shard->hpa_sec);
21*c43cad87SWarner Losh 	}
22*c43cad87SWarner Losh }
23*c43cad87SWarner Losh 
24*c43cad87SWarner Losh void
25*c43cad87SWarner Losh pa_shard_prefork3(tsdn_t *tsdn, pa_shard_t *shard) {
26*c43cad87SWarner Losh 	malloc_mutex_prefork(tsdn, &shard->pac.grow_mtx);
27*c43cad87SWarner Losh 	if (shard->ever_used_hpa) {
28*c43cad87SWarner Losh 		hpa_shard_prefork3(tsdn, &shard->hpa_shard);
29*c43cad87SWarner Losh 	}
30*c43cad87SWarner Losh }
31*c43cad87SWarner Losh 
32*c43cad87SWarner Losh void
33*c43cad87SWarner Losh pa_shard_prefork4(tsdn_t *tsdn, pa_shard_t *shard) {
34*c43cad87SWarner Losh 	ecache_prefork(tsdn, &shard->pac.ecache_dirty);
35*c43cad87SWarner Losh 	ecache_prefork(tsdn, &shard->pac.ecache_muzzy);
36*c43cad87SWarner Losh 	ecache_prefork(tsdn, &shard->pac.ecache_retained);
37*c43cad87SWarner Losh 	if (shard->ever_used_hpa) {
38*c43cad87SWarner Losh 		hpa_shard_prefork4(tsdn, &shard->hpa_shard);
39*c43cad87SWarner Losh 	}
40*c43cad87SWarner Losh }
41*c43cad87SWarner Losh 
42*c43cad87SWarner Losh void
43*c43cad87SWarner Losh pa_shard_prefork5(tsdn_t *tsdn, pa_shard_t *shard) {
44*c43cad87SWarner Losh 	edata_cache_prefork(tsdn, &shard->edata_cache);
45*c43cad87SWarner Losh }
46*c43cad87SWarner Losh 
47*c43cad87SWarner Losh void
48*c43cad87SWarner Losh pa_shard_postfork_parent(tsdn_t *tsdn, pa_shard_t *shard) {
49*c43cad87SWarner Losh 	edata_cache_postfork_parent(tsdn, &shard->edata_cache);
50*c43cad87SWarner Losh 	ecache_postfork_parent(tsdn, &shard->pac.ecache_dirty);
51*c43cad87SWarner Losh 	ecache_postfork_parent(tsdn, &shard->pac.ecache_muzzy);
52*c43cad87SWarner Losh 	ecache_postfork_parent(tsdn, &shard->pac.ecache_retained);
53*c43cad87SWarner Losh 	malloc_mutex_postfork_parent(tsdn, &shard->pac.grow_mtx);
54*c43cad87SWarner Losh 	malloc_mutex_postfork_parent(tsdn, &shard->pac.decay_dirty.mtx);
55*c43cad87SWarner Losh 	malloc_mutex_postfork_parent(tsdn, &shard->pac.decay_muzzy.mtx);
56*c43cad87SWarner Losh 	if (shard->ever_used_hpa) {
57*c43cad87SWarner Losh 		sec_postfork_parent(tsdn, &shard->hpa_sec);
58*c43cad87SWarner Losh 		hpa_shard_postfork_parent(tsdn, &shard->hpa_shard);
59*c43cad87SWarner Losh 	}
60*c43cad87SWarner Losh }
61*c43cad87SWarner Losh 
62*c43cad87SWarner Losh void
63*c43cad87SWarner Losh pa_shard_postfork_child(tsdn_t *tsdn, pa_shard_t *shard) {
64*c43cad87SWarner Losh 	edata_cache_postfork_child(tsdn, &shard->edata_cache);
65*c43cad87SWarner Losh 	ecache_postfork_child(tsdn, &shard->pac.ecache_dirty);
66*c43cad87SWarner Losh 	ecache_postfork_child(tsdn, &shard->pac.ecache_muzzy);
67*c43cad87SWarner Losh 	ecache_postfork_child(tsdn, &shard->pac.ecache_retained);
68*c43cad87SWarner Losh 	malloc_mutex_postfork_child(tsdn, &shard->pac.grow_mtx);
69*c43cad87SWarner Losh 	malloc_mutex_postfork_child(tsdn, &shard->pac.decay_dirty.mtx);
70*c43cad87SWarner Losh 	malloc_mutex_postfork_child(tsdn, &shard->pac.decay_muzzy.mtx);
71*c43cad87SWarner Losh 	if (shard->ever_used_hpa) {
72*c43cad87SWarner Losh 		sec_postfork_child(tsdn, &shard->hpa_sec);
73*c43cad87SWarner Losh 		hpa_shard_postfork_child(tsdn, &shard->hpa_shard);
74*c43cad87SWarner Losh 	}
75*c43cad87SWarner Losh }
76*c43cad87SWarner Losh 
77*c43cad87SWarner Losh void
78*c43cad87SWarner Losh pa_shard_basic_stats_merge(pa_shard_t *shard, size_t *nactive, size_t *ndirty,
79*c43cad87SWarner Losh     size_t *nmuzzy) {
80*c43cad87SWarner Losh 	*nactive += atomic_load_zu(&shard->nactive, ATOMIC_RELAXED);
81*c43cad87SWarner Losh 	*ndirty += ecache_npages_get(&shard->pac.ecache_dirty);
82*c43cad87SWarner Losh 	*nmuzzy += ecache_npages_get(&shard->pac.ecache_muzzy);
83*c43cad87SWarner Losh }
84*c43cad87SWarner Losh 
85*c43cad87SWarner Losh void
86*c43cad87SWarner Losh pa_shard_stats_merge(tsdn_t *tsdn, pa_shard_t *shard,
87*c43cad87SWarner Losh     pa_shard_stats_t *pa_shard_stats_out, pac_estats_t *estats_out,
88*c43cad87SWarner Losh     hpa_shard_stats_t *hpa_stats_out, sec_stats_t *sec_stats_out,
89*c43cad87SWarner Losh     size_t *resident) {
90*c43cad87SWarner Losh 	cassert(config_stats);
91*c43cad87SWarner Losh 
92*c43cad87SWarner Losh 	pa_shard_stats_out->pac_stats.retained +=
93*c43cad87SWarner Losh 	    ecache_npages_get(&shard->pac.ecache_retained) << LG_PAGE;
94*c43cad87SWarner Losh 	pa_shard_stats_out->edata_avail += atomic_load_zu(
95*c43cad87SWarner Losh 	    &shard->edata_cache.count, ATOMIC_RELAXED);
96*c43cad87SWarner Losh 
97*c43cad87SWarner Losh 	size_t resident_pgs = 0;
98*c43cad87SWarner Losh 	resident_pgs += atomic_load_zu(&shard->nactive, ATOMIC_RELAXED);
99*c43cad87SWarner Losh 	resident_pgs += ecache_npages_get(&shard->pac.ecache_dirty);
100*c43cad87SWarner Losh 	*resident += (resident_pgs << LG_PAGE);
101*c43cad87SWarner Losh 
102*c43cad87SWarner Losh 	/* Dirty decay stats */
103*c43cad87SWarner Losh 	locked_inc_u64_unsynchronized(
104*c43cad87SWarner Losh 	    &pa_shard_stats_out->pac_stats.decay_dirty.npurge,
105*c43cad87SWarner Losh 	    locked_read_u64(tsdn, LOCKEDINT_MTX(*shard->stats_mtx),
106*c43cad87SWarner Losh 	    &shard->pac.stats->decay_dirty.npurge));
107*c43cad87SWarner Losh 	locked_inc_u64_unsynchronized(
108*c43cad87SWarner Losh 	    &pa_shard_stats_out->pac_stats.decay_dirty.nmadvise,
109*c43cad87SWarner Losh 	    locked_read_u64(tsdn, LOCKEDINT_MTX(*shard->stats_mtx),
110*c43cad87SWarner Losh 	    &shard->pac.stats->decay_dirty.nmadvise));
111*c43cad87SWarner Losh 	locked_inc_u64_unsynchronized(
112*c43cad87SWarner Losh 	    &pa_shard_stats_out->pac_stats.decay_dirty.purged,
113*c43cad87SWarner Losh 	    locked_read_u64(tsdn, LOCKEDINT_MTX(*shard->stats_mtx),
114*c43cad87SWarner Losh 	    &shard->pac.stats->decay_dirty.purged));
115*c43cad87SWarner Losh 
116*c43cad87SWarner Losh 	/* Muzzy decay stats */
117*c43cad87SWarner Losh 	locked_inc_u64_unsynchronized(
118*c43cad87SWarner Losh 	    &pa_shard_stats_out->pac_stats.decay_muzzy.npurge,
119*c43cad87SWarner Losh 	    locked_read_u64(tsdn, LOCKEDINT_MTX(*shard->stats_mtx),
120*c43cad87SWarner Losh 	    &shard->pac.stats->decay_muzzy.npurge));
121*c43cad87SWarner Losh 	locked_inc_u64_unsynchronized(
122*c43cad87SWarner Losh 	    &pa_shard_stats_out->pac_stats.decay_muzzy.nmadvise,
123*c43cad87SWarner Losh 	    locked_read_u64(tsdn, LOCKEDINT_MTX(*shard->stats_mtx),
124*c43cad87SWarner Losh 	    &shard->pac.stats->decay_muzzy.nmadvise));
125*c43cad87SWarner Losh 	locked_inc_u64_unsynchronized(
126*c43cad87SWarner Losh 	    &pa_shard_stats_out->pac_stats.decay_muzzy.purged,
127*c43cad87SWarner Losh 	    locked_read_u64(tsdn, LOCKEDINT_MTX(*shard->stats_mtx),
128*c43cad87SWarner Losh 	    &shard->pac.stats->decay_muzzy.purged));
129*c43cad87SWarner Losh 
130*c43cad87SWarner Losh 	atomic_load_add_store_zu(&pa_shard_stats_out->pac_stats.abandoned_vm,
131*c43cad87SWarner Losh 	    atomic_load_zu(&shard->pac.stats->abandoned_vm, ATOMIC_RELAXED));
132*c43cad87SWarner Losh 
133*c43cad87SWarner Losh 	for (pszind_t i = 0; i < SC_NPSIZES; i++) {
134*c43cad87SWarner Losh 		size_t dirty, muzzy, retained, dirty_bytes, muzzy_bytes,
135*c43cad87SWarner Losh 		    retained_bytes;
136*c43cad87SWarner Losh 		dirty = ecache_nextents_get(&shard->pac.ecache_dirty, i);
137*c43cad87SWarner Losh 		muzzy = ecache_nextents_get(&shard->pac.ecache_muzzy, i);
138*c43cad87SWarner Losh 		retained = ecache_nextents_get(&shard->pac.ecache_retained, i);
139*c43cad87SWarner Losh 		dirty_bytes = ecache_nbytes_get(&shard->pac.ecache_dirty, i);
140*c43cad87SWarner Losh 		muzzy_bytes = ecache_nbytes_get(&shard->pac.ecache_muzzy, i);
141*c43cad87SWarner Losh 		retained_bytes = ecache_nbytes_get(&shard->pac.ecache_retained,
142*c43cad87SWarner Losh 		    i);
143*c43cad87SWarner Losh 
144*c43cad87SWarner Losh 		estats_out[i].ndirty = dirty;
145*c43cad87SWarner Losh 		estats_out[i].nmuzzy = muzzy;
146*c43cad87SWarner Losh 		estats_out[i].nretained = retained;
147*c43cad87SWarner Losh 		estats_out[i].dirty_bytes = dirty_bytes;
148*c43cad87SWarner Losh 		estats_out[i].muzzy_bytes = muzzy_bytes;
149*c43cad87SWarner Losh 		estats_out[i].retained_bytes = retained_bytes;
150*c43cad87SWarner Losh 	}
151*c43cad87SWarner Losh 
152*c43cad87SWarner Losh 	if (shard->ever_used_hpa) {
153*c43cad87SWarner Losh 		hpa_shard_stats_merge(tsdn, &shard->hpa_shard, hpa_stats_out);
154*c43cad87SWarner Losh 		sec_stats_merge(tsdn, &shard->hpa_sec, sec_stats_out);
155*c43cad87SWarner Losh 	}
156*c43cad87SWarner Losh }
157*c43cad87SWarner Losh 
158*c43cad87SWarner Losh static void
159*c43cad87SWarner Losh pa_shard_mtx_stats_read_single(tsdn_t *tsdn, mutex_prof_data_t *mutex_prof_data,
160*c43cad87SWarner Losh     malloc_mutex_t *mtx, int ind) {
161*c43cad87SWarner Losh 	malloc_mutex_lock(tsdn, mtx);
162*c43cad87SWarner Losh 	malloc_mutex_prof_read(tsdn, &mutex_prof_data[ind], mtx);
163*c43cad87SWarner Losh 	malloc_mutex_unlock(tsdn, mtx);
164*c43cad87SWarner Losh }
165*c43cad87SWarner Losh 
166*c43cad87SWarner Losh void
167*c43cad87SWarner Losh pa_shard_mtx_stats_read(tsdn_t *tsdn, pa_shard_t *shard,
168*c43cad87SWarner Losh     mutex_prof_data_t mutex_prof_data[mutex_prof_num_arena_mutexes]) {
169*c43cad87SWarner Losh 	pa_shard_mtx_stats_read_single(tsdn, mutex_prof_data,
170*c43cad87SWarner Losh 	    &shard->edata_cache.mtx, arena_prof_mutex_extent_avail);
171*c43cad87SWarner Losh 	pa_shard_mtx_stats_read_single(tsdn, mutex_prof_data,
172*c43cad87SWarner Losh 	    &shard->pac.ecache_dirty.mtx, arena_prof_mutex_extents_dirty);
173*c43cad87SWarner Losh 	pa_shard_mtx_stats_read_single(tsdn, mutex_prof_data,
174*c43cad87SWarner Losh 	    &shard->pac.ecache_muzzy.mtx, arena_prof_mutex_extents_muzzy);
175*c43cad87SWarner Losh 	pa_shard_mtx_stats_read_single(tsdn, mutex_prof_data,
176*c43cad87SWarner Losh 	    &shard->pac.ecache_retained.mtx, arena_prof_mutex_extents_retained);
177*c43cad87SWarner Losh 	pa_shard_mtx_stats_read_single(tsdn, mutex_prof_data,
178*c43cad87SWarner Losh 	    &shard->pac.decay_dirty.mtx, arena_prof_mutex_decay_dirty);
179*c43cad87SWarner Losh 	pa_shard_mtx_stats_read_single(tsdn, mutex_prof_data,
180*c43cad87SWarner Losh 	    &shard->pac.decay_muzzy.mtx, arena_prof_mutex_decay_muzzy);
181*c43cad87SWarner Losh 
182*c43cad87SWarner Losh 	if (shard->ever_used_hpa) {
183*c43cad87SWarner Losh 		pa_shard_mtx_stats_read_single(tsdn, mutex_prof_data,
184*c43cad87SWarner Losh 		    &shard->hpa_shard.mtx, arena_prof_mutex_hpa_shard);
185*c43cad87SWarner Losh 		pa_shard_mtx_stats_read_single(tsdn, mutex_prof_data,
186*c43cad87SWarner Losh 		    &shard->hpa_shard.grow_mtx,
187*c43cad87SWarner Losh 		    arena_prof_mutex_hpa_shard_grow);
188*c43cad87SWarner Losh 		sec_mutex_stats_read(tsdn, &shard->hpa_sec,
189*c43cad87SWarner Losh 		    &mutex_prof_data[arena_prof_mutex_hpa_sec]);
190*c43cad87SWarner Losh 	}
191*c43cad87SWarner Losh }
192