xref: /aosp_15_r20/external/jemalloc_new/include/jemalloc/internal/tsd.h (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #ifndef JEMALLOC_INTERNAL_TSD_H
2*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_INTERNAL_TSD_H
3*1208bc7eSAndroid Build Coastguard Worker 
4*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/arena_types.h"
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/assert.h"
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_internal_externs.h"
7*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/prof_types.h"
8*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/ql.h"
9*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/rtree_tsd.h"
10*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/tcache_types.h"
11*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/tcache_structs.h"
12*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/util.h"
13*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/witness.h"
14*1208bc7eSAndroid Build Coastguard Worker 
15*1208bc7eSAndroid Build Coastguard Worker /*
16*1208bc7eSAndroid Build Coastguard Worker  * Thread-Specific-Data layout
17*1208bc7eSAndroid Build Coastguard Worker  * --- data accessed on tcache fast path: state, rtree_ctx, stats, prof ---
18*1208bc7eSAndroid Build Coastguard Worker  * s: state
19*1208bc7eSAndroid Build Coastguard Worker  * e: tcache_enabled
20*1208bc7eSAndroid Build Coastguard Worker  * m: thread_allocated (config_stats)
21*1208bc7eSAndroid Build Coastguard Worker  * f: thread_deallocated (config_stats)
22*1208bc7eSAndroid Build Coastguard Worker  * p: prof_tdata (config_prof)
23*1208bc7eSAndroid Build Coastguard Worker  * c: rtree_ctx (rtree cache accessed on deallocation)
24*1208bc7eSAndroid Build Coastguard Worker  * t: tcache
25*1208bc7eSAndroid Build Coastguard Worker  * --- data not accessed on tcache fast path: arena-related fields ---
26*1208bc7eSAndroid Build Coastguard Worker  * d: arenas_tdata_bypass
27*1208bc7eSAndroid Build Coastguard Worker  * r: reentrancy_level
28*1208bc7eSAndroid Build Coastguard Worker  * x: narenas_tdata
29*1208bc7eSAndroid Build Coastguard Worker  * i: iarena
30*1208bc7eSAndroid Build Coastguard Worker  * a: arena
31*1208bc7eSAndroid Build Coastguard Worker  * o: arenas_tdata
32*1208bc7eSAndroid Build Coastguard Worker  * Loading TSD data is on the critical path of basically all malloc operations.
33*1208bc7eSAndroid Build Coastguard Worker  * In particular, tcache and rtree_ctx rely on hot CPU cache to be effective.
34*1208bc7eSAndroid Build Coastguard Worker  * Use a compact layout to reduce cache footprint.
35*1208bc7eSAndroid Build Coastguard Worker  * +--- 64-bit and 64B cacheline; 1B each letter; First byte on the left. ---+
36*1208bc7eSAndroid Build Coastguard Worker  * |----------------------------  1st cacheline  ----------------------------|
37*1208bc7eSAndroid Build Coastguard Worker  * | sedrxxxx mmmmmmmm ffffffff pppppppp [c * 32  ........ ........ .......] |
38*1208bc7eSAndroid Build Coastguard Worker  * |----------------------------  2nd cacheline  ----------------------------|
39*1208bc7eSAndroid Build Coastguard Worker  * | [c * 64  ........ ........ ........ ........ ........ ........ .......] |
40*1208bc7eSAndroid Build Coastguard Worker  * |----------------------------  3nd cacheline  ----------------------------|
41*1208bc7eSAndroid Build Coastguard Worker  * | [c * 32  ........ ........ .......] iiiiiiii aaaaaaaa oooooooo [t...... |
42*1208bc7eSAndroid Build Coastguard Worker  * +-------------------------------------------------------------------------+
43*1208bc7eSAndroid Build Coastguard Worker  * Note: the entire tcache is embedded into TSD and spans multiple cachelines.
44*1208bc7eSAndroid Build Coastguard Worker  *
45*1208bc7eSAndroid Build Coastguard Worker  * The last 3 members (i, a and o) before tcache isn't really needed on tcache
46*1208bc7eSAndroid Build Coastguard Worker  * fast path.  However we have a number of unused tcache bins and witnesses
47*1208bc7eSAndroid Build Coastguard Worker  * (never touched unless config_debug) at the end of tcache, so we place them
48*1208bc7eSAndroid Build Coastguard Worker  * there to avoid breaking the cachelines and possibly paging in an extra page.
49*1208bc7eSAndroid Build Coastguard Worker  */
50*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_JET
51*1208bc7eSAndroid Build Coastguard Worker typedef void (*test_callback_t)(int *);
52*1208bc7eSAndroid Build Coastguard Worker #  define MALLOC_TSD_TEST_DATA_INIT 0x72b65c10
53*1208bc7eSAndroid Build Coastguard Worker #  define MALLOC_TEST_TSD \
54*1208bc7eSAndroid Build Coastguard Worker     O(test_data,		int,			int)		\
55*1208bc7eSAndroid Build Coastguard Worker     O(test_callback,		test_callback_t,	int)
56*1208bc7eSAndroid Build Coastguard Worker #  define MALLOC_TEST_TSD_INITIALIZER , MALLOC_TSD_TEST_DATA_INIT, NULL
57*1208bc7eSAndroid Build Coastguard Worker #else
58*1208bc7eSAndroid Build Coastguard Worker #  define MALLOC_TEST_TSD
59*1208bc7eSAndroid Build Coastguard Worker #  define MALLOC_TEST_TSD_INITIALIZER
60*1208bc7eSAndroid Build Coastguard Worker #endif
61*1208bc7eSAndroid Build Coastguard Worker 
62*1208bc7eSAndroid Build Coastguard Worker /*  O(name,			type,			nullable type */
63*1208bc7eSAndroid Build Coastguard Worker #define MALLOC_TSD							\
64*1208bc7eSAndroid Build Coastguard Worker     O(tcache_enabled,		bool,			bool)		\
65*1208bc7eSAndroid Build Coastguard Worker     O(arenas_tdata_bypass,	bool,			bool)		\
66*1208bc7eSAndroid Build Coastguard Worker     O(reentrancy_level,		int8_t,			int8_t)		\
67*1208bc7eSAndroid Build Coastguard Worker     O(narenas_tdata,		uint32_t,		uint32_t)	\
68*1208bc7eSAndroid Build Coastguard Worker     O(offset_state,		uint64_t,		uint64_t)	\
69*1208bc7eSAndroid Build Coastguard Worker     O(thread_allocated,		uint64_t,		uint64_t)	\
70*1208bc7eSAndroid Build Coastguard Worker     O(thread_deallocated,	uint64_t,		uint64_t)	\
71*1208bc7eSAndroid Build Coastguard Worker     O(prof_tdata,		prof_tdata_t *,		prof_tdata_t *)	\
72*1208bc7eSAndroid Build Coastguard Worker     O(rtree_ctx,		rtree_ctx_t,		rtree_ctx_t)	\
73*1208bc7eSAndroid Build Coastguard Worker     O(iarena,			arena_t *,		arena_t *)	\
74*1208bc7eSAndroid Build Coastguard Worker     O(arena,			arena_t *,		arena_t *)	\
75*1208bc7eSAndroid Build Coastguard Worker     O(arenas_tdata,		arena_tdata_t *,	arena_tdata_t *)\
76*1208bc7eSAndroid Build Coastguard Worker     O(tcache,			tcache_t,		tcache_t)	\
77*1208bc7eSAndroid Build Coastguard Worker     O(witness_tsd,              witness_tsd_t,		witness_tsdn_t)	\
78*1208bc7eSAndroid Build Coastguard Worker     MALLOC_TEST_TSD
79*1208bc7eSAndroid Build Coastguard Worker 
80*1208bc7eSAndroid Build Coastguard Worker #define TSD_INITIALIZER {						\
81*1208bc7eSAndroid Build Coastguard Worker     tsd_state_uninitialized,						\
82*1208bc7eSAndroid Build Coastguard Worker     TCACHE_ENABLED_ZERO_INITIALIZER,					\
83*1208bc7eSAndroid Build Coastguard Worker     false,								\
84*1208bc7eSAndroid Build Coastguard Worker     0,									\
85*1208bc7eSAndroid Build Coastguard Worker     0,									\
86*1208bc7eSAndroid Build Coastguard Worker     0,									\
87*1208bc7eSAndroid Build Coastguard Worker     0,									\
88*1208bc7eSAndroid Build Coastguard Worker     0,									\
89*1208bc7eSAndroid Build Coastguard Worker     NULL,								\
90*1208bc7eSAndroid Build Coastguard Worker     RTREE_CTX_ZERO_INITIALIZER,						\
91*1208bc7eSAndroid Build Coastguard Worker     NULL,								\
92*1208bc7eSAndroid Build Coastguard Worker     NULL,								\
93*1208bc7eSAndroid Build Coastguard Worker     NULL,								\
94*1208bc7eSAndroid Build Coastguard Worker     TCACHE_ZERO_INITIALIZER,						\
95*1208bc7eSAndroid Build Coastguard Worker     WITNESS_TSD_INITIALIZER						\
96*1208bc7eSAndroid Build Coastguard Worker     MALLOC_TEST_TSD_INITIALIZER						\
97*1208bc7eSAndroid Build Coastguard Worker }
98*1208bc7eSAndroid Build Coastguard Worker 
99*1208bc7eSAndroid Build Coastguard Worker enum {
100*1208bc7eSAndroid Build Coastguard Worker 	tsd_state_nominal = 0, /* Common case --> jnz. */
101*1208bc7eSAndroid Build Coastguard Worker 	tsd_state_nominal_slow = 1, /* Initialized but on slow path. */
102*1208bc7eSAndroid Build Coastguard Worker 	/* the above 2 nominal states should be lower values. */
103*1208bc7eSAndroid Build Coastguard Worker 	tsd_state_nominal_max = 1, /* used for comparison only. */
104*1208bc7eSAndroid Build Coastguard Worker 	tsd_state_minimal_initialized = 2,
105*1208bc7eSAndroid Build Coastguard Worker 	tsd_state_purgatory = 3,
106*1208bc7eSAndroid Build Coastguard Worker 	tsd_state_reincarnated = 4,
107*1208bc7eSAndroid Build Coastguard Worker 	tsd_state_uninitialized = 5
108*1208bc7eSAndroid Build Coastguard Worker };
109*1208bc7eSAndroid Build Coastguard Worker 
110*1208bc7eSAndroid Build Coastguard Worker /* Manually limit tsd_state_t to a single byte. */
111*1208bc7eSAndroid Build Coastguard Worker typedef uint8_t tsd_state_t;
112*1208bc7eSAndroid Build Coastguard Worker 
113*1208bc7eSAndroid Build Coastguard Worker /* The actual tsd. */
114*1208bc7eSAndroid Build Coastguard Worker struct tsd_s {
115*1208bc7eSAndroid Build Coastguard Worker 	/*
116*1208bc7eSAndroid Build Coastguard Worker 	 * The contents should be treated as totally opaque outside the tsd
117*1208bc7eSAndroid Build Coastguard Worker 	 * module.  Access any thread-local state through the getters and
118*1208bc7eSAndroid Build Coastguard Worker 	 * setters below.
119*1208bc7eSAndroid Build Coastguard Worker 	 */
120*1208bc7eSAndroid Build Coastguard Worker 	tsd_state_t	state;
121*1208bc7eSAndroid Build Coastguard Worker #define O(n, t, nt)							\
122*1208bc7eSAndroid Build Coastguard Worker 	t use_a_getter_or_setter_instead_##n;
123*1208bc7eSAndroid Build Coastguard Worker MALLOC_TSD
124*1208bc7eSAndroid Build Coastguard Worker #undef O
125*1208bc7eSAndroid Build Coastguard Worker };
126*1208bc7eSAndroid Build Coastguard Worker 
127*1208bc7eSAndroid Build Coastguard Worker /*
128*1208bc7eSAndroid Build Coastguard Worker  * Wrapper around tsd_t that makes it possible to avoid implicit conversion
129*1208bc7eSAndroid Build Coastguard Worker  * between tsd_t and tsdn_t, where tsdn_t is "nullable" and has to be
130*1208bc7eSAndroid Build Coastguard Worker  * explicitly converted to tsd_t, which is non-nullable.
131*1208bc7eSAndroid Build Coastguard Worker  */
132*1208bc7eSAndroid Build Coastguard Worker struct tsdn_s {
133*1208bc7eSAndroid Build Coastguard Worker 	tsd_t tsd;
134*1208bc7eSAndroid Build Coastguard Worker };
135*1208bc7eSAndroid Build Coastguard Worker #define TSDN_NULL ((tsdn_t *)0)
136*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE tsdn_t *
tsd_tsdn(tsd_t * tsd)137*1208bc7eSAndroid Build Coastguard Worker tsd_tsdn(tsd_t *tsd) {
138*1208bc7eSAndroid Build Coastguard Worker 	return (tsdn_t *)tsd;
139*1208bc7eSAndroid Build Coastguard Worker }
140*1208bc7eSAndroid Build Coastguard Worker 
141*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
tsdn_null(const tsdn_t * tsdn)142*1208bc7eSAndroid Build Coastguard Worker tsdn_null(const tsdn_t *tsdn) {
143*1208bc7eSAndroid Build Coastguard Worker 	return tsdn == NULL;
144*1208bc7eSAndroid Build Coastguard Worker }
145*1208bc7eSAndroid Build Coastguard Worker 
146*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE tsd_t *
tsdn_tsd(tsdn_t * tsdn)147*1208bc7eSAndroid Build Coastguard Worker tsdn_tsd(tsdn_t *tsdn) {
148*1208bc7eSAndroid Build Coastguard Worker 	assert(!tsdn_null(tsdn));
149*1208bc7eSAndroid Build Coastguard Worker 
150*1208bc7eSAndroid Build Coastguard Worker 	return &tsdn->tsd;
151*1208bc7eSAndroid Build Coastguard Worker }
152*1208bc7eSAndroid Build Coastguard Worker 
153*1208bc7eSAndroid Build Coastguard Worker void *malloc_tsd_malloc(size_t size);
154*1208bc7eSAndroid Build Coastguard Worker void malloc_tsd_dalloc(void *wrapper);
155*1208bc7eSAndroid Build Coastguard Worker void malloc_tsd_cleanup_register(bool (*f)(void));
156*1208bc7eSAndroid Build Coastguard Worker tsd_t *malloc_tsd_boot0(void);
157*1208bc7eSAndroid Build Coastguard Worker void malloc_tsd_boot1(void);
158*1208bc7eSAndroid Build Coastguard Worker void tsd_cleanup(void *arg);
159*1208bc7eSAndroid Build Coastguard Worker tsd_t *tsd_fetch_slow(tsd_t *tsd, bool internal);
160*1208bc7eSAndroid Build Coastguard Worker void tsd_slow_update(tsd_t *tsd);
161*1208bc7eSAndroid Build Coastguard Worker 
162*1208bc7eSAndroid Build Coastguard Worker /*
163*1208bc7eSAndroid Build Coastguard Worker  * We put the platform-specific data declarations and inlines into their own
164*1208bc7eSAndroid Build Coastguard Worker  * header files to avoid cluttering this file.  They define tsd_boot0,
165*1208bc7eSAndroid Build Coastguard Worker  * tsd_boot1, tsd_boot, tsd_booted_get, tsd_get_allocates, tsd_get, and tsd_set.
166*1208bc7eSAndroid Build Coastguard Worker  */
167*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_MALLOC_THREAD_CLEANUP
168*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/tsd_malloc_thread_cleanup.h"
169*1208bc7eSAndroid Build Coastguard Worker #elif (defined(JEMALLOC_TLS))
170*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/tsd_tls.h"
171*1208bc7eSAndroid Build Coastguard Worker #elif (defined(_WIN32))
172*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/tsd_win.h"
173*1208bc7eSAndroid Build Coastguard Worker #else
174*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/tsd_generic.h"
175*1208bc7eSAndroid Build Coastguard Worker #endif
176*1208bc7eSAndroid Build Coastguard Worker 
177*1208bc7eSAndroid Build Coastguard Worker /*
178*1208bc7eSAndroid Build Coastguard Worker  * tsd_foop_get_unsafe(tsd) returns a pointer to the thread-local instance of
179*1208bc7eSAndroid Build Coastguard Worker  * foo.  This omits some safety checks, and so can be used during tsd
180*1208bc7eSAndroid Build Coastguard Worker  * initialization and cleanup.
181*1208bc7eSAndroid Build Coastguard Worker  */
182*1208bc7eSAndroid Build Coastguard Worker #define O(n, t, nt)							\
183*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE t *						\
184*1208bc7eSAndroid Build Coastguard Worker tsd_##n##p_get_unsafe(tsd_t *tsd) {					\
185*1208bc7eSAndroid Build Coastguard Worker 	return &tsd->use_a_getter_or_setter_instead_##n;		\
186*1208bc7eSAndroid Build Coastguard Worker }
187*1208bc7eSAndroid Build Coastguard Worker MALLOC_TSD
188*1208bc7eSAndroid Build Coastguard Worker #undef O
189*1208bc7eSAndroid Build Coastguard Worker 
190*1208bc7eSAndroid Build Coastguard Worker /* tsd_foop_get(tsd) returns a pointer to the thread-local instance of foo. */
191*1208bc7eSAndroid Build Coastguard Worker #define O(n, t, nt)							\
192*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE t *						\
193*1208bc7eSAndroid Build Coastguard Worker tsd_##n##p_get(tsd_t *tsd) {						\
194*1208bc7eSAndroid Build Coastguard Worker 	assert(tsd->state == tsd_state_nominal ||			\
195*1208bc7eSAndroid Build Coastguard Worker 	    tsd->state == tsd_state_nominal_slow ||			\
196*1208bc7eSAndroid Build Coastguard Worker 	    tsd->state == tsd_state_reincarnated ||			\
197*1208bc7eSAndroid Build Coastguard Worker 	    tsd->state == tsd_state_minimal_initialized);		\
198*1208bc7eSAndroid Build Coastguard Worker 	return tsd_##n##p_get_unsafe(tsd);				\
199*1208bc7eSAndroid Build Coastguard Worker }
200*1208bc7eSAndroid Build Coastguard Worker MALLOC_TSD
201*1208bc7eSAndroid Build Coastguard Worker #undef O
202*1208bc7eSAndroid Build Coastguard Worker 
203*1208bc7eSAndroid Build Coastguard Worker /*
204*1208bc7eSAndroid Build Coastguard Worker  * tsdn_foop_get(tsdn) returns either the thread-local instance of foo (if tsdn
205*1208bc7eSAndroid Build Coastguard Worker  * isn't NULL), or NULL (if tsdn is NULL), cast to the nullable pointer type.
206*1208bc7eSAndroid Build Coastguard Worker  */
207*1208bc7eSAndroid Build Coastguard Worker #define O(n, t, nt)							\
208*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE nt *						\
209*1208bc7eSAndroid Build Coastguard Worker tsdn_##n##p_get(tsdn_t *tsdn) {						\
210*1208bc7eSAndroid Build Coastguard Worker 	if (tsdn_null(tsdn)) {						\
211*1208bc7eSAndroid Build Coastguard Worker 		return NULL;						\
212*1208bc7eSAndroid Build Coastguard Worker 	}								\
213*1208bc7eSAndroid Build Coastguard Worker 	tsd_t *tsd = tsdn_tsd(tsdn);					\
214*1208bc7eSAndroid Build Coastguard Worker 	return (nt *)tsd_##n##p_get(tsd);				\
215*1208bc7eSAndroid Build Coastguard Worker }
216*1208bc7eSAndroid Build Coastguard Worker MALLOC_TSD
217*1208bc7eSAndroid Build Coastguard Worker #undef O
218*1208bc7eSAndroid Build Coastguard Worker 
219*1208bc7eSAndroid Build Coastguard Worker /* tsd_foo_get(tsd) returns the value of the thread-local instance of foo. */
220*1208bc7eSAndroid Build Coastguard Worker #define O(n, t, nt)							\
221*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE t						\
222*1208bc7eSAndroid Build Coastguard Worker tsd_##n##_get(tsd_t *tsd) {						\
223*1208bc7eSAndroid Build Coastguard Worker 	return *tsd_##n##p_get(tsd);					\
224*1208bc7eSAndroid Build Coastguard Worker }
225*1208bc7eSAndroid Build Coastguard Worker MALLOC_TSD
226*1208bc7eSAndroid Build Coastguard Worker #undef O
227*1208bc7eSAndroid Build Coastguard Worker 
228*1208bc7eSAndroid Build Coastguard Worker /* tsd_foo_set(tsd, val) updates the thread-local instance of foo to be val. */
229*1208bc7eSAndroid Build Coastguard Worker #define O(n, t, nt)							\
230*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void						\
231*1208bc7eSAndroid Build Coastguard Worker tsd_##n##_set(tsd_t *tsd, t val) {					\
232*1208bc7eSAndroid Build Coastguard Worker 	assert(tsd->state != tsd_state_reincarnated &&			\
233*1208bc7eSAndroid Build Coastguard Worker 	    tsd->state != tsd_state_minimal_initialized);		\
234*1208bc7eSAndroid Build Coastguard Worker 	*tsd_##n##p_get(tsd) = val;					\
235*1208bc7eSAndroid Build Coastguard Worker }
236*1208bc7eSAndroid Build Coastguard Worker MALLOC_TSD
237*1208bc7eSAndroid Build Coastguard Worker #undef O
238*1208bc7eSAndroid Build Coastguard Worker 
239*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE void
tsd_assert_fast(tsd_t * tsd)240*1208bc7eSAndroid Build Coastguard Worker tsd_assert_fast(tsd_t *tsd) {
241*1208bc7eSAndroid Build Coastguard Worker 	assert(!malloc_slow && tsd_tcache_enabled_get(tsd) &&
242*1208bc7eSAndroid Build Coastguard Worker 	    tsd_reentrancy_level_get(tsd) == 0);
243*1208bc7eSAndroid Build Coastguard Worker }
244*1208bc7eSAndroid Build Coastguard Worker 
245*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
tsd_fast(tsd_t * tsd)246*1208bc7eSAndroid Build Coastguard Worker tsd_fast(tsd_t *tsd) {
247*1208bc7eSAndroid Build Coastguard Worker 	bool fast = (tsd->state == tsd_state_nominal);
248*1208bc7eSAndroid Build Coastguard Worker 	if (fast) {
249*1208bc7eSAndroid Build Coastguard Worker 		tsd_assert_fast(tsd);
250*1208bc7eSAndroid Build Coastguard Worker 	}
251*1208bc7eSAndroid Build Coastguard Worker 
252*1208bc7eSAndroid Build Coastguard Worker 	return fast;
253*1208bc7eSAndroid Build Coastguard Worker }
254*1208bc7eSAndroid Build Coastguard Worker 
255*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_fetch_impl(bool init,bool minimal)256*1208bc7eSAndroid Build Coastguard Worker tsd_fetch_impl(bool init, bool minimal) {
257*1208bc7eSAndroid Build Coastguard Worker 	tsd_t *tsd = tsd_get(init);
258*1208bc7eSAndroid Build Coastguard Worker 
259*1208bc7eSAndroid Build Coastguard Worker 	if (!init && tsd_get_allocates() && tsd == NULL) {
260*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
261*1208bc7eSAndroid Build Coastguard Worker 	}
262*1208bc7eSAndroid Build Coastguard Worker 	assert(tsd != NULL);
263*1208bc7eSAndroid Build Coastguard Worker 
264*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(tsd->state != tsd_state_nominal)) {
265*1208bc7eSAndroid Build Coastguard Worker 		return tsd_fetch_slow(tsd, minimal);
266*1208bc7eSAndroid Build Coastguard Worker 	}
267*1208bc7eSAndroid Build Coastguard Worker 	assert(tsd_fast(tsd));
268*1208bc7eSAndroid Build Coastguard Worker 	tsd_assert_fast(tsd);
269*1208bc7eSAndroid Build Coastguard Worker 
270*1208bc7eSAndroid Build Coastguard Worker 	return tsd;
271*1208bc7eSAndroid Build Coastguard Worker }
272*1208bc7eSAndroid Build Coastguard Worker 
273*1208bc7eSAndroid Build Coastguard Worker /* Get a minimal TSD that requires no cleanup.  See comments in free(). */
274*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_fetch_min(void)275*1208bc7eSAndroid Build Coastguard Worker tsd_fetch_min(void) {
276*1208bc7eSAndroid Build Coastguard Worker 	return tsd_fetch_impl(true, true);
277*1208bc7eSAndroid Build Coastguard Worker }
278*1208bc7eSAndroid Build Coastguard Worker 
279*1208bc7eSAndroid Build Coastguard Worker /* For internal background threads use only. */
280*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_internal_fetch(void)281*1208bc7eSAndroid Build Coastguard Worker tsd_internal_fetch(void) {
282*1208bc7eSAndroid Build Coastguard Worker 	tsd_t *tsd = tsd_fetch_min();
283*1208bc7eSAndroid Build Coastguard Worker 	/* Use reincarnated state to prevent full initialization. */
284*1208bc7eSAndroid Build Coastguard Worker 	tsd->state = tsd_state_reincarnated;
285*1208bc7eSAndroid Build Coastguard Worker 
286*1208bc7eSAndroid Build Coastguard Worker 	return tsd;
287*1208bc7eSAndroid Build Coastguard Worker }
288*1208bc7eSAndroid Build Coastguard Worker 
289*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE tsd_t *
tsd_fetch(void)290*1208bc7eSAndroid Build Coastguard Worker tsd_fetch(void) {
291*1208bc7eSAndroid Build Coastguard Worker 	return tsd_fetch_impl(true, false);
292*1208bc7eSAndroid Build Coastguard Worker }
293*1208bc7eSAndroid Build Coastguard Worker 
294*1208bc7eSAndroid Build Coastguard Worker static inline bool
tsd_nominal(tsd_t * tsd)295*1208bc7eSAndroid Build Coastguard Worker tsd_nominal(tsd_t *tsd) {
296*1208bc7eSAndroid Build Coastguard Worker 	return (tsd->state <= tsd_state_nominal_max);
297*1208bc7eSAndroid Build Coastguard Worker }
298*1208bc7eSAndroid Build Coastguard Worker 
299*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE tsdn_t *
tsdn_fetch(void)300*1208bc7eSAndroid Build Coastguard Worker tsdn_fetch(void) {
301*1208bc7eSAndroid Build Coastguard Worker 	if (!tsd_booted_get()) {
302*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
303*1208bc7eSAndroid Build Coastguard Worker 	}
304*1208bc7eSAndroid Build Coastguard Worker 
305*1208bc7eSAndroid Build Coastguard Worker 	return tsd_tsdn(tsd_fetch_impl(false, false));
306*1208bc7eSAndroid Build Coastguard Worker }
307*1208bc7eSAndroid Build Coastguard Worker 
308*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE rtree_ctx_t *
tsd_rtree_ctx(tsd_t * tsd)309*1208bc7eSAndroid Build Coastguard Worker tsd_rtree_ctx(tsd_t *tsd) {
310*1208bc7eSAndroid Build Coastguard Worker 	return tsd_rtree_ctxp_get(tsd);
311*1208bc7eSAndroid Build Coastguard Worker }
312*1208bc7eSAndroid Build Coastguard Worker 
313*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE rtree_ctx_t *
tsdn_rtree_ctx(tsdn_t * tsdn,rtree_ctx_t * fallback)314*1208bc7eSAndroid Build Coastguard Worker tsdn_rtree_ctx(tsdn_t *tsdn, rtree_ctx_t *fallback) {
315*1208bc7eSAndroid Build Coastguard Worker 	/*
316*1208bc7eSAndroid Build Coastguard Worker 	 * If tsd cannot be accessed, initialize the fallback rtree_ctx and
317*1208bc7eSAndroid Build Coastguard Worker 	 * return a pointer to it.
318*1208bc7eSAndroid Build Coastguard Worker 	 */
319*1208bc7eSAndroid Build Coastguard Worker 	if (unlikely(tsdn_null(tsdn))) {
320*1208bc7eSAndroid Build Coastguard Worker 		rtree_ctx_data_init(fallback);
321*1208bc7eSAndroid Build Coastguard Worker 		return fallback;
322*1208bc7eSAndroid Build Coastguard Worker 	}
323*1208bc7eSAndroid Build Coastguard Worker 	return tsd_rtree_ctx(tsdn_tsd(tsdn));
324*1208bc7eSAndroid Build Coastguard Worker }
325*1208bc7eSAndroid Build Coastguard Worker 
326*1208bc7eSAndroid Build Coastguard Worker #endif /* JEMALLOC_INTERNAL_TSD_H */
327