xref: /netbsd-src/external/bsd/jemalloc.old/include/jemalloc/internal/tcache_inlines.h (revision 8e33eff89e26cf71871ead62f0d5063e1313c33a)
1*8e33eff8Schristos #ifndef JEMALLOC_INTERNAL_TCACHE_INLINES_H
2*8e33eff8Schristos #define JEMALLOC_INTERNAL_TCACHE_INLINES_H
3*8e33eff8Schristos 
4*8e33eff8Schristos #include "jemalloc/internal/bin.h"
5*8e33eff8Schristos #include "jemalloc/internal/jemalloc_internal_types.h"
6*8e33eff8Schristos #include "jemalloc/internal/size_classes.h"
7*8e33eff8Schristos #include "jemalloc/internal/sz.h"
8*8e33eff8Schristos #include "jemalloc/internal/ticker.h"
9*8e33eff8Schristos #include "jemalloc/internal/util.h"
10*8e33eff8Schristos 
11*8e33eff8Schristos static inline bool
12*8e33eff8Schristos tcache_enabled_get(tsd_t *tsd) {
13*8e33eff8Schristos 	return tsd_tcache_enabled_get(tsd);
14*8e33eff8Schristos }
15*8e33eff8Schristos 
16*8e33eff8Schristos static inline void
17*8e33eff8Schristos tcache_enabled_set(tsd_t *tsd, bool enabled) {
18*8e33eff8Schristos 	bool was_enabled = tsd_tcache_enabled_get(tsd);
19*8e33eff8Schristos 
20*8e33eff8Schristos 	if (!was_enabled && enabled) {
21*8e33eff8Schristos 		tsd_tcache_data_init(tsd);
22*8e33eff8Schristos 	} else if (was_enabled && !enabled) {
23*8e33eff8Schristos 		tcache_cleanup(tsd);
24*8e33eff8Schristos 	}
25*8e33eff8Schristos 	/* Commit the state last.  Above calls check current state. */
26*8e33eff8Schristos 	tsd_tcache_enabled_set(tsd, enabled);
27*8e33eff8Schristos 	tsd_slow_update(tsd);
28*8e33eff8Schristos }
29*8e33eff8Schristos 
30*8e33eff8Schristos JEMALLOC_ALWAYS_INLINE void
31*8e33eff8Schristos tcache_event(tsd_t *tsd, tcache_t *tcache) {
32*8e33eff8Schristos 	if (TCACHE_GC_INCR == 0) {
33*8e33eff8Schristos 		return;
34*8e33eff8Schristos 	}
35*8e33eff8Schristos 
36*8e33eff8Schristos 	if (unlikely(ticker_tick(&tcache->gc_ticker))) {
37*8e33eff8Schristos 		tcache_event_hard(tsd, tcache);
38*8e33eff8Schristos 	}
39*8e33eff8Schristos }
40*8e33eff8Schristos 
41*8e33eff8Schristos JEMALLOC_ALWAYS_INLINE void *
42*8e33eff8Schristos tcache_alloc_small(tsd_t *tsd, arena_t *arena, tcache_t *tcache,
43*8e33eff8Schristos     UNUSED size_t size, szind_t binind, bool zero, bool slow_path) {
44*8e33eff8Schristos 	void *ret;
45*8e33eff8Schristos 	cache_bin_t *bin;
46*8e33eff8Schristos 	bool tcache_success;
47*8e33eff8Schristos 	size_t usize JEMALLOC_CC_SILENCE_INIT(0);
48*8e33eff8Schristos 
49*8e33eff8Schristos 	assert(binind < NBINS);
50*8e33eff8Schristos 	bin = tcache_small_bin_get(tcache, binind);
51*8e33eff8Schristos 	ret = cache_bin_alloc_easy(bin, &tcache_success);
52*8e33eff8Schristos 	assert(tcache_success == (ret != NULL));
53*8e33eff8Schristos 	if (unlikely(!tcache_success)) {
54*8e33eff8Schristos 		bool tcache_hard_success;
55*8e33eff8Schristos 		arena = arena_choose(tsd, arena);
56*8e33eff8Schristos 		if (unlikely(arena == NULL)) {
57*8e33eff8Schristos 			return NULL;
58*8e33eff8Schristos 		}
59*8e33eff8Schristos 
60*8e33eff8Schristos 		ret = tcache_alloc_small_hard(tsd_tsdn(tsd), arena, tcache,
61*8e33eff8Schristos 		    bin, binind, &tcache_hard_success);
62*8e33eff8Schristos 		if (tcache_hard_success == false) {
63*8e33eff8Schristos 			return NULL;
64*8e33eff8Schristos 		}
65*8e33eff8Schristos 	}
66*8e33eff8Schristos 
67*8e33eff8Schristos 	assert(ret);
68*8e33eff8Schristos 	/*
69*8e33eff8Schristos 	 * Only compute usize if required.  The checks in the following if
70*8e33eff8Schristos 	 * statement are all static.
71*8e33eff8Schristos 	 */
72*8e33eff8Schristos 	if (config_prof || (slow_path && config_fill) || unlikely(zero)) {
73*8e33eff8Schristos 		usize = sz_index2size(binind);
74*8e33eff8Schristos 		assert(tcache_salloc(tsd_tsdn(tsd), ret) == usize);
75*8e33eff8Schristos 	}
76*8e33eff8Schristos 
77*8e33eff8Schristos 	if (likely(!zero)) {
78*8e33eff8Schristos 		if (slow_path && config_fill) {
79*8e33eff8Schristos 			if (unlikely(opt_junk_alloc)) {
80*8e33eff8Schristos 				arena_alloc_junk_small(ret, &bin_infos[binind],
81*8e33eff8Schristos 				    false);
82*8e33eff8Schristos 			} else if (unlikely(opt_zero)) {
83*8e33eff8Schristos 				memset(ret, 0, usize);
84*8e33eff8Schristos 			}
85*8e33eff8Schristos 		}
86*8e33eff8Schristos 	} else {
87*8e33eff8Schristos 		if (slow_path && config_fill && unlikely(opt_junk_alloc)) {
88*8e33eff8Schristos 			arena_alloc_junk_small(ret, &bin_infos[binind], true);
89*8e33eff8Schristos 		}
90*8e33eff8Schristos 		memset(ret, 0, usize);
91*8e33eff8Schristos 	}
92*8e33eff8Schristos 
93*8e33eff8Schristos 	if (config_stats) {
94*8e33eff8Schristos 		bin->tstats.nrequests++;
95*8e33eff8Schristos 	}
96*8e33eff8Schristos 	if (config_prof) {
97*8e33eff8Schristos 		tcache->prof_accumbytes += usize;
98*8e33eff8Schristos 	}
99*8e33eff8Schristos 	tcache_event(tsd, tcache);
100*8e33eff8Schristos 	return ret;
101*8e33eff8Schristos }
102*8e33eff8Schristos 
103*8e33eff8Schristos JEMALLOC_ALWAYS_INLINE void *
104*8e33eff8Schristos tcache_alloc_large(tsd_t *tsd, arena_t *arena, tcache_t *tcache, size_t size,
105*8e33eff8Schristos     szind_t binind, bool zero, bool slow_path) {
106*8e33eff8Schristos 	void *ret;
107*8e33eff8Schristos 	cache_bin_t *bin;
108*8e33eff8Schristos 	bool tcache_success;
109*8e33eff8Schristos 
110*8e33eff8Schristos 	assert(binind >= NBINS &&binind < nhbins);
111*8e33eff8Schristos 	bin = tcache_large_bin_get(tcache, binind);
112*8e33eff8Schristos 	ret = cache_bin_alloc_easy(bin, &tcache_success);
113*8e33eff8Schristos 	assert(tcache_success == (ret != NULL));
114*8e33eff8Schristos 	if (unlikely(!tcache_success)) {
115*8e33eff8Schristos 		/*
116*8e33eff8Schristos 		 * Only allocate one large object at a time, because it's quite
117*8e33eff8Schristos 		 * expensive to create one and not use it.
118*8e33eff8Schristos 		 */
119*8e33eff8Schristos 		arena = arena_choose(tsd, arena);
120*8e33eff8Schristos 		if (unlikely(arena == NULL)) {
121*8e33eff8Schristos 			return NULL;
122*8e33eff8Schristos 		}
123*8e33eff8Schristos 
124*8e33eff8Schristos 		ret = large_malloc(tsd_tsdn(tsd), arena, sz_s2u(size), zero);
125*8e33eff8Schristos 		if (ret == NULL) {
126*8e33eff8Schristos 			return NULL;
127*8e33eff8Schristos 		}
128*8e33eff8Schristos 	} else {
129*8e33eff8Schristos 		size_t usize JEMALLOC_CC_SILENCE_INIT(0);
130*8e33eff8Schristos 
131*8e33eff8Schristos 		/* Only compute usize on demand */
132*8e33eff8Schristos 		if (config_prof || (slow_path && config_fill) ||
133*8e33eff8Schristos 		    unlikely(zero)) {
134*8e33eff8Schristos 			usize = sz_index2size(binind);
135*8e33eff8Schristos 			assert(usize <= tcache_maxclass);
136*8e33eff8Schristos 		}
137*8e33eff8Schristos 
138*8e33eff8Schristos 		if (likely(!zero)) {
139*8e33eff8Schristos 			if (slow_path && config_fill) {
140*8e33eff8Schristos 				if (unlikely(opt_junk_alloc)) {
141*8e33eff8Schristos 					memset(ret, JEMALLOC_ALLOC_JUNK,
142*8e33eff8Schristos 					    usize);
143*8e33eff8Schristos 				} else if (unlikely(opt_zero)) {
144*8e33eff8Schristos 					memset(ret, 0, usize);
145*8e33eff8Schristos 				}
146*8e33eff8Schristos 			}
147*8e33eff8Schristos 		} else {
148*8e33eff8Schristos 			memset(ret, 0, usize);
149*8e33eff8Schristos 		}
150*8e33eff8Schristos 
151*8e33eff8Schristos 		if (config_stats) {
152*8e33eff8Schristos 			bin->tstats.nrequests++;
153*8e33eff8Schristos 		}
154*8e33eff8Schristos 		if (config_prof) {
155*8e33eff8Schristos 			tcache->prof_accumbytes += usize;
156*8e33eff8Schristos 		}
157*8e33eff8Schristos 	}
158*8e33eff8Schristos 
159*8e33eff8Schristos 	tcache_event(tsd, tcache);
160*8e33eff8Schristos 	return ret;
161*8e33eff8Schristos }
162*8e33eff8Schristos 
163*8e33eff8Schristos JEMALLOC_ALWAYS_INLINE void
164*8e33eff8Schristos tcache_dalloc_small(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind,
165*8e33eff8Schristos     bool slow_path) {
166*8e33eff8Schristos 	cache_bin_t *bin;
167*8e33eff8Schristos 	cache_bin_info_t *bin_info;
168*8e33eff8Schristos 
169*8e33eff8Schristos 	assert(tcache_salloc(tsd_tsdn(tsd), ptr) <= SMALL_MAXCLASS);
170*8e33eff8Schristos 
171*8e33eff8Schristos 	if (slow_path && config_fill && unlikely(opt_junk_free)) {
172*8e33eff8Schristos 		arena_dalloc_junk_small(ptr, &bin_infos[binind]);
173*8e33eff8Schristos 	}
174*8e33eff8Schristos 
175*8e33eff8Schristos 	bin = tcache_small_bin_get(tcache, binind);
176*8e33eff8Schristos 	bin_info = &tcache_bin_info[binind];
177*8e33eff8Schristos 	if (unlikely(bin->ncached == bin_info->ncached_max)) {
178*8e33eff8Schristos 		tcache_bin_flush_small(tsd, tcache, bin, binind,
179*8e33eff8Schristos 		    (bin_info->ncached_max >> 1));
180*8e33eff8Schristos 	}
181*8e33eff8Schristos 	assert(bin->ncached < bin_info->ncached_max);
182*8e33eff8Schristos 	bin->ncached++;
183*8e33eff8Schristos 	*(bin->avail - bin->ncached) = ptr;
184*8e33eff8Schristos 
185*8e33eff8Schristos 	tcache_event(tsd, tcache);
186*8e33eff8Schristos }
187*8e33eff8Schristos 
188*8e33eff8Schristos JEMALLOC_ALWAYS_INLINE void
189*8e33eff8Schristos tcache_dalloc_large(tsd_t *tsd, tcache_t *tcache, void *ptr, szind_t binind,
190*8e33eff8Schristos     bool slow_path) {
191*8e33eff8Schristos 	cache_bin_t *bin;
192*8e33eff8Schristos 	cache_bin_info_t *bin_info;
193*8e33eff8Schristos 
194*8e33eff8Schristos 	assert(tcache_salloc(tsd_tsdn(tsd), ptr) > SMALL_MAXCLASS);
195*8e33eff8Schristos 	assert(tcache_salloc(tsd_tsdn(tsd), ptr) <= tcache_maxclass);
196*8e33eff8Schristos 
197*8e33eff8Schristos 	if (slow_path && config_fill && unlikely(opt_junk_free)) {
198*8e33eff8Schristos 		large_dalloc_junk(ptr, sz_index2size(binind));
199*8e33eff8Schristos 	}
200*8e33eff8Schristos 
201*8e33eff8Schristos 	bin = tcache_large_bin_get(tcache, binind);
202*8e33eff8Schristos 	bin_info = &tcache_bin_info[binind];
203*8e33eff8Schristos 	if (unlikely(bin->ncached == bin_info->ncached_max)) {
204*8e33eff8Schristos 		tcache_bin_flush_large(tsd, bin, binind,
205*8e33eff8Schristos 		    (bin_info->ncached_max >> 1), tcache);
206*8e33eff8Schristos 	}
207*8e33eff8Schristos 	assert(bin->ncached < bin_info->ncached_max);
208*8e33eff8Schristos 	bin->ncached++;
209*8e33eff8Schristos 	*(bin->avail - bin->ncached) = ptr;
210*8e33eff8Schristos 
211*8e33eff8Schristos 	tcache_event(tsd, tcache);
212*8e33eff8Schristos }
213*8e33eff8Schristos 
214*8e33eff8Schristos JEMALLOC_ALWAYS_INLINE tcache_t *
215*8e33eff8Schristos tcaches_get(tsd_t *tsd, unsigned ind) {
216*8e33eff8Schristos 	tcaches_t *elm = &tcaches[ind];
217*8e33eff8Schristos 	if (unlikely(elm->tcache == NULL)) {
218*8e33eff8Schristos 		elm->tcache = tcache_create_explicit(tsd);
219*8e33eff8Schristos 	}
220*8e33eff8Schristos 	return elm->tcache;
221*8e33eff8Schristos }
222*8e33eff8Schristos 
223*8e33eff8Schristos #endif /* JEMALLOC_INTERNAL_TCACHE_INLINES_H */
224