xref: /aosp_15_r20/external/jemalloc_new/include/jemalloc/internal/rtree.h (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #ifndef JEMALLOC_INTERNAL_RTREE_H
2*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_INTERNAL_RTREE_H
3*1208bc7eSAndroid Build Coastguard Worker 
4*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/atomic.h"
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/mutex.h"
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/rtree_tsd.h"
7*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/size_classes.h"
8*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/tsd.h"
9*1208bc7eSAndroid Build Coastguard Worker 
10*1208bc7eSAndroid Build Coastguard Worker /*
11*1208bc7eSAndroid Build Coastguard Worker  * This radix tree implementation is tailored to the singular purpose of
12*1208bc7eSAndroid Build Coastguard Worker  * associating metadata with extents that are currently owned by jemalloc.
13*1208bc7eSAndroid Build Coastguard Worker  *
14*1208bc7eSAndroid Build Coastguard Worker  *******************************************************************************
15*1208bc7eSAndroid Build Coastguard Worker  */
16*1208bc7eSAndroid Build Coastguard Worker 
17*1208bc7eSAndroid Build Coastguard Worker /* Number of high insignificant bits. */
18*1208bc7eSAndroid Build Coastguard Worker #define RTREE_NHIB ((1U << (LG_SIZEOF_PTR+3)) - LG_VADDR)
19*1208bc7eSAndroid Build Coastguard Worker /* Number of low insigificant bits. */
20*1208bc7eSAndroid Build Coastguard Worker #define RTREE_NLIB LG_PAGE
21*1208bc7eSAndroid Build Coastguard Worker /* Number of significant bits. */
22*1208bc7eSAndroid Build Coastguard Worker #define RTREE_NSB (LG_VADDR - RTREE_NLIB)
23*1208bc7eSAndroid Build Coastguard Worker /* Number of levels in radix tree. */
24*1208bc7eSAndroid Build Coastguard Worker #if RTREE_NSB <= 10
25*1208bc7eSAndroid Build Coastguard Worker #  define RTREE_HEIGHT 1
26*1208bc7eSAndroid Build Coastguard Worker #elif RTREE_NSB <= 36
27*1208bc7eSAndroid Build Coastguard Worker #  define RTREE_HEIGHT 2
28*1208bc7eSAndroid Build Coastguard Worker #elif RTREE_NSB <= 52
29*1208bc7eSAndroid Build Coastguard Worker #  define RTREE_HEIGHT 3
30*1208bc7eSAndroid Build Coastguard Worker #else
31*1208bc7eSAndroid Build Coastguard Worker #  error Unsupported number of significant virtual address bits
32*1208bc7eSAndroid Build Coastguard Worker #endif
33*1208bc7eSAndroid Build Coastguard Worker /* Use compact leaf representation if virtual address encoding allows. */
34*1208bc7eSAndroid Build Coastguard Worker #if RTREE_NHIB >= LG_CEIL_NSIZES
35*1208bc7eSAndroid Build Coastguard Worker #  define RTREE_LEAF_COMPACT
36*1208bc7eSAndroid Build Coastguard Worker #endif
37*1208bc7eSAndroid Build Coastguard Worker 
38*1208bc7eSAndroid Build Coastguard Worker /* Needed for initialization only. */
39*1208bc7eSAndroid Build Coastguard Worker #define RTREE_LEAFKEY_INVALID ((uintptr_t)1)
40*1208bc7eSAndroid Build Coastguard Worker 
41*1208bc7eSAndroid Build Coastguard Worker typedef struct rtree_node_elm_s rtree_node_elm_t;
42*1208bc7eSAndroid Build Coastguard Worker struct rtree_node_elm_s {
43*1208bc7eSAndroid Build Coastguard Worker 	atomic_p_t	child; /* (rtree_{node,leaf}_elm_t *) */
44*1208bc7eSAndroid Build Coastguard Worker };
45*1208bc7eSAndroid Build Coastguard Worker 
46*1208bc7eSAndroid Build Coastguard Worker struct rtree_leaf_elm_s {
47*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
48*1208bc7eSAndroid Build Coastguard Worker 	/*
49*1208bc7eSAndroid Build Coastguard Worker 	 * Single pointer-width field containing all three leaf element fields.
50*1208bc7eSAndroid Build Coastguard Worker 	 * For example, on a 64-bit x64 system with 48 significant virtual
51*1208bc7eSAndroid Build Coastguard Worker 	 * memory address bits, the index, extent, and slab fields are packed as
52*1208bc7eSAndroid Build Coastguard Worker 	 * such:
53*1208bc7eSAndroid Build Coastguard Worker 	 *
54*1208bc7eSAndroid Build Coastguard Worker 	 * x: index
55*1208bc7eSAndroid Build Coastguard Worker 	 * e: extent
56*1208bc7eSAndroid Build Coastguard Worker 	 * b: slab
57*1208bc7eSAndroid Build Coastguard Worker 	 *
58*1208bc7eSAndroid Build Coastguard Worker 	 *   00000000 xxxxxxxx eeeeeeee [...] eeeeeeee eeee000b
59*1208bc7eSAndroid Build Coastguard Worker 	 */
60*1208bc7eSAndroid Build Coastguard Worker 	atomic_p_t	le_bits;
61*1208bc7eSAndroid Build Coastguard Worker #else
62*1208bc7eSAndroid Build Coastguard Worker 	atomic_p_t	le_extent; /* (extent_t *) */
63*1208bc7eSAndroid Build Coastguard Worker 	atomic_u_t	le_szind; /* (szind_t) */
64*1208bc7eSAndroid Build Coastguard Worker 	atomic_b_t	le_slab; /* (bool) */
65*1208bc7eSAndroid Build Coastguard Worker #endif
66*1208bc7eSAndroid Build Coastguard Worker };
67*1208bc7eSAndroid Build Coastguard Worker 
68*1208bc7eSAndroid Build Coastguard Worker typedef struct rtree_level_s rtree_level_t;
69*1208bc7eSAndroid Build Coastguard Worker struct rtree_level_s {
70*1208bc7eSAndroid Build Coastguard Worker 	/* Number of key bits distinguished by this level. */
71*1208bc7eSAndroid Build Coastguard Worker 	unsigned		bits;
72*1208bc7eSAndroid Build Coastguard Worker 	/*
73*1208bc7eSAndroid Build Coastguard Worker 	 * Cumulative number of key bits distinguished by traversing to
74*1208bc7eSAndroid Build Coastguard Worker 	 * corresponding tree level.
75*1208bc7eSAndroid Build Coastguard Worker 	 */
76*1208bc7eSAndroid Build Coastguard Worker 	unsigned		cumbits;
77*1208bc7eSAndroid Build Coastguard Worker };
78*1208bc7eSAndroid Build Coastguard Worker 
79*1208bc7eSAndroid Build Coastguard Worker typedef struct rtree_s rtree_t;
80*1208bc7eSAndroid Build Coastguard Worker struct rtree_s {
81*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_t		init_lock;
82*1208bc7eSAndroid Build Coastguard Worker 	/* Number of elements based on rtree_levels[0].bits. */
83*1208bc7eSAndroid Build Coastguard Worker #if RTREE_HEIGHT > 1
84*1208bc7eSAndroid Build Coastguard Worker 	rtree_node_elm_t	root[1U << (RTREE_NSB/RTREE_HEIGHT)];
85*1208bc7eSAndroid Build Coastguard Worker #else
86*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t	root[1U << (RTREE_NSB/RTREE_HEIGHT)];
87*1208bc7eSAndroid Build Coastguard Worker #endif
88*1208bc7eSAndroid Build Coastguard Worker };
89*1208bc7eSAndroid Build Coastguard Worker 
90*1208bc7eSAndroid Build Coastguard Worker /*
91*1208bc7eSAndroid Build Coastguard Worker  * Split the bits into one to three partitions depending on number of
92*1208bc7eSAndroid Build Coastguard Worker  * significant bits.  It the number of bits does not divide evenly into the
93*1208bc7eSAndroid Build Coastguard Worker  * number of levels, place one remainder bit per level starting at the leaf
94*1208bc7eSAndroid Build Coastguard Worker  * level.
95*1208bc7eSAndroid Build Coastguard Worker  */
96*1208bc7eSAndroid Build Coastguard Worker static const rtree_level_t rtree_levels[] = {
97*1208bc7eSAndroid Build Coastguard Worker #if RTREE_HEIGHT == 1
98*1208bc7eSAndroid Build Coastguard Worker 	{RTREE_NSB, RTREE_NHIB + RTREE_NSB}
99*1208bc7eSAndroid Build Coastguard Worker #elif RTREE_HEIGHT == 2
100*1208bc7eSAndroid Build Coastguard Worker 	{RTREE_NSB/2, RTREE_NHIB + RTREE_NSB/2},
101*1208bc7eSAndroid Build Coastguard Worker 	{RTREE_NSB/2 + RTREE_NSB%2, RTREE_NHIB + RTREE_NSB}
102*1208bc7eSAndroid Build Coastguard Worker #elif RTREE_HEIGHT == 3
103*1208bc7eSAndroid Build Coastguard Worker 	{RTREE_NSB/3, RTREE_NHIB + RTREE_NSB/3},
104*1208bc7eSAndroid Build Coastguard Worker 	{RTREE_NSB/3 + RTREE_NSB%3/2,
105*1208bc7eSAndroid Build Coastguard Worker 	    RTREE_NHIB + RTREE_NSB/3*2 + RTREE_NSB%3/2},
106*1208bc7eSAndroid Build Coastguard Worker 	{RTREE_NSB/3 + RTREE_NSB%3 - RTREE_NSB%3/2, RTREE_NHIB + RTREE_NSB}
107*1208bc7eSAndroid Build Coastguard Worker #else
108*1208bc7eSAndroid Build Coastguard Worker #  error Unsupported rtree height
109*1208bc7eSAndroid Build Coastguard Worker #endif
110*1208bc7eSAndroid Build Coastguard Worker };
111*1208bc7eSAndroid Build Coastguard Worker 
112*1208bc7eSAndroid Build Coastguard Worker bool rtree_new(rtree_t *rtree, bool zeroed);
113*1208bc7eSAndroid Build Coastguard Worker 
114*1208bc7eSAndroid Build Coastguard Worker typedef rtree_node_elm_t *(rtree_node_alloc_t)(tsdn_t *, rtree_t *, size_t);
115*1208bc7eSAndroid Build Coastguard Worker extern rtree_node_alloc_t *JET_MUTABLE rtree_node_alloc;
116*1208bc7eSAndroid Build Coastguard Worker 
117*1208bc7eSAndroid Build Coastguard Worker typedef rtree_leaf_elm_t *(rtree_leaf_alloc_t)(tsdn_t *, rtree_t *, size_t);
118*1208bc7eSAndroid Build Coastguard Worker extern rtree_leaf_alloc_t *JET_MUTABLE rtree_leaf_alloc;
119*1208bc7eSAndroid Build Coastguard Worker 
120*1208bc7eSAndroid Build Coastguard Worker typedef void (rtree_node_dalloc_t)(tsdn_t *, rtree_t *, rtree_node_elm_t *);
121*1208bc7eSAndroid Build Coastguard Worker extern rtree_node_dalloc_t *JET_MUTABLE rtree_node_dalloc;
122*1208bc7eSAndroid Build Coastguard Worker 
123*1208bc7eSAndroid Build Coastguard Worker typedef void (rtree_leaf_dalloc_t)(tsdn_t *, rtree_t *, rtree_leaf_elm_t *);
124*1208bc7eSAndroid Build Coastguard Worker extern rtree_leaf_dalloc_t *JET_MUTABLE rtree_leaf_dalloc;
125*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_JET
126*1208bc7eSAndroid Build Coastguard Worker void rtree_delete(tsdn_t *tsdn, rtree_t *rtree);
127*1208bc7eSAndroid Build Coastguard Worker #endif
128*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_t *rtree_leaf_elm_lookup_hard(tsdn_t *tsdn, rtree_t *rtree,
129*1208bc7eSAndroid Build Coastguard Worker     rtree_ctx_t *rtree_ctx, uintptr_t key, bool dependent, bool init_missing);
130*1208bc7eSAndroid Build Coastguard Worker 
131*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE uintptr_t
rtree_leafkey(uintptr_t key)132*1208bc7eSAndroid Build Coastguard Worker rtree_leafkey(uintptr_t key) {
133*1208bc7eSAndroid Build Coastguard Worker 	unsigned ptrbits = ZU(1) << (LG_SIZEOF_PTR+3);
134*1208bc7eSAndroid Build Coastguard Worker 	unsigned cumbits = (rtree_levels[RTREE_HEIGHT-1].cumbits -
135*1208bc7eSAndroid Build Coastguard Worker 	    rtree_levels[RTREE_HEIGHT-1].bits);
136*1208bc7eSAndroid Build Coastguard Worker 	unsigned maskbits = ptrbits - cumbits;
137*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t mask = ~((ZU(1) << maskbits) - 1);
138*1208bc7eSAndroid Build Coastguard Worker 	return (key & mask);
139*1208bc7eSAndroid Build Coastguard Worker }
140*1208bc7eSAndroid Build Coastguard Worker 
141*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE size_t
rtree_cache_direct_map(uintptr_t key)142*1208bc7eSAndroid Build Coastguard Worker rtree_cache_direct_map(uintptr_t key) {
143*1208bc7eSAndroid Build Coastguard Worker 	unsigned ptrbits = ZU(1) << (LG_SIZEOF_PTR+3);
144*1208bc7eSAndroid Build Coastguard Worker 	unsigned cumbits = (rtree_levels[RTREE_HEIGHT-1].cumbits -
145*1208bc7eSAndroid Build Coastguard Worker 	    rtree_levels[RTREE_HEIGHT-1].bits);
146*1208bc7eSAndroid Build Coastguard Worker 	unsigned maskbits = ptrbits - cumbits;
147*1208bc7eSAndroid Build Coastguard Worker 	return (size_t)((key >> maskbits) & (RTREE_CTX_NCACHE - 1));
148*1208bc7eSAndroid Build Coastguard Worker }
149*1208bc7eSAndroid Build Coastguard Worker 
150*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE uintptr_t
rtree_subkey(uintptr_t key,unsigned level)151*1208bc7eSAndroid Build Coastguard Worker rtree_subkey(uintptr_t key, unsigned level) {
152*1208bc7eSAndroid Build Coastguard Worker 	unsigned ptrbits = ZU(1) << (LG_SIZEOF_PTR+3);
153*1208bc7eSAndroid Build Coastguard Worker 	unsigned cumbits = rtree_levels[level].cumbits;
154*1208bc7eSAndroid Build Coastguard Worker 	unsigned shiftbits = ptrbits - cumbits;
155*1208bc7eSAndroid Build Coastguard Worker 	unsigned maskbits = rtree_levels[level].bits;
156*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t mask = (ZU(1) << maskbits) - 1;
157*1208bc7eSAndroid Build Coastguard Worker 	return ((key >> shiftbits) & mask);
158*1208bc7eSAndroid Build Coastguard Worker }
159*1208bc7eSAndroid Build Coastguard Worker 
160*1208bc7eSAndroid Build Coastguard Worker /*
161*1208bc7eSAndroid Build Coastguard Worker  * Atomic getters.
162*1208bc7eSAndroid Build Coastguard Worker  *
163*1208bc7eSAndroid Build Coastguard Worker  * dependent: Reading a value on behalf of a pointer to a valid allocation
164*1208bc7eSAndroid Build Coastguard Worker  *            is guaranteed to be a clean read even without synchronization,
165*1208bc7eSAndroid Build Coastguard Worker  *            because the rtree update became visible in memory before the
166*1208bc7eSAndroid Build Coastguard Worker  *            pointer came into existence.
167*1208bc7eSAndroid Build Coastguard Worker  * !dependent: An arbitrary read, e.g. on behalf of ivsalloc(), may not be
168*1208bc7eSAndroid Build Coastguard Worker  *             dependent on a previous rtree write, which means a stale read
169*1208bc7eSAndroid Build Coastguard Worker  *             could result if synchronization were omitted here.
170*1208bc7eSAndroid Build Coastguard Worker  */
171*1208bc7eSAndroid Build Coastguard Worker #  ifdef RTREE_LEAF_COMPACT
172*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE uintptr_t
rtree_leaf_elm_bits_read(tsdn_t * tsdn,rtree_t * rtree,rtree_leaf_elm_t * elm,bool dependent)173*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_bits_read(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm,
174*1208bc7eSAndroid Build Coastguard Worker     bool dependent) {
175*1208bc7eSAndroid Build Coastguard Worker 	return (uintptr_t)atomic_load_p(&elm->le_bits, dependent
176*1208bc7eSAndroid Build Coastguard Worker 	    ? ATOMIC_RELAXED : ATOMIC_ACQUIRE);
177*1208bc7eSAndroid Build Coastguard Worker }
178*1208bc7eSAndroid Build Coastguard Worker 
179*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE extent_t *
rtree_leaf_elm_bits_extent_get(uintptr_t bits)180*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_bits_extent_get(uintptr_t bits) {
181*1208bc7eSAndroid Build Coastguard Worker #    ifdef __aarch64__
182*1208bc7eSAndroid Build Coastguard Worker 	/*
183*1208bc7eSAndroid Build Coastguard Worker 	 * aarch64 doesn't sign extend the highest virtual address bit to set
184*1208bc7eSAndroid Build Coastguard Worker 	 * the higher ones.  Instead, the high bits gets zeroed.
185*1208bc7eSAndroid Build Coastguard Worker 	 */
186*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t high_bit_mask = ((uintptr_t)1 << LG_VADDR) - 1;
187*1208bc7eSAndroid Build Coastguard Worker 	/* Mask off the slab bit. */
188*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t low_bit_mask = ~(uintptr_t)1;
189*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t mask = high_bit_mask & low_bit_mask;
190*1208bc7eSAndroid Build Coastguard Worker 	return (extent_t *)(bits & mask);
191*1208bc7eSAndroid Build Coastguard Worker #    else
192*1208bc7eSAndroid Build Coastguard Worker 	/* Restore sign-extended high bits, mask slab bit. */
193*1208bc7eSAndroid Build Coastguard Worker 	return (extent_t *)((uintptr_t)((intptr_t)(bits << RTREE_NHIB) >>
194*1208bc7eSAndroid Build Coastguard Worker 	    RTREE_NHIB) & ~((uintptr_t)0x1));
195*1208bc7eSAndroid Build Coastguard Worker #    endif
196*1208bc7eSAndroid Build Coastguard Worker }
197*1208bc7eSAndroid Build Coastguard Worker 
198*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE szind_t
rtree_leaf_elm_bits_szind_get(uintptr_t bits)199*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_bits_szind_get(uintptr_t bits) {
200*1208bc7eSAndroid Build Coastguard Worker 	return (szind_t)(bits >> LG_VADDR);
201*1208bc7eSAndroid Build Coastguard Worker }
202*1208bc7eSAndroid Build Coastguard Worker 
203*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
rtree_leaf_elm_bits_slab_get(uintptr_t bits)204*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_bits_slab_get(uintptr_t bits) {
205*1208bc7eSAndroid Build Coastguard Worker 	return (bool)(bits & (uintptr_t)0x1);
206*1208bc7eSAndroid Build Coastguard Worker }
207*1208bc7eSAndroid Build Coastguard Worker 
208*1208bc7eSAndroid Build Coastguard Worker #  endif
209*1208bc7eSAndroid Build Coastguard Worker 
210*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE extent_t *
rtree_leaf_elm_extent_read(UNUSED tsdn_t * tsdn,UNUSED rtree_t * rtree,rtree_leaf_elm_t * elm,bool dependent)211*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_extent_read(UNUSED tsdn_t *tsdn, UNUSED rtree_t *rtree,
212*1208bc7eSAndroid Build Coastguard Worker     rtree_leaf_elm_t *elm, bool dependent) {
213*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
214*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent);
215*1208bc7eSAndroid Build Coastguard Worker 	return rtree_leaf_elm_bits_extent_get(bits);
216*1208bc7eSAndroid Build Coastguard Worker #else
217*1208bc7eSAndroid Build Coastguard Worker 	extent_t *extent = (extent_t *)atomic_load_p(&elm->le_extent, dependent
218*1208bc7eSAndroid Build Coastguard Worker 	    ? ATOMIC_RELAXED : ATOMIC_ACQUIRE);
219*1208bc7eSAndroid Build Coastguard Worker 	return extent;
220*1208bc7eSAndroid Build Coastguard Worker #endif
221*1208bc7eSAndroid Build Coastguard Worker }
222*1208bc7eSAndroid Build Coastguard Worker 
223*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE szind_t
rtree_leaf_elm_szind_read(UNUSED tsdn_t * tsdn,UNUSED rtree_t * rtree,rtree_leaf_elm_t * elm,bool dependent)224*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_szind_read(UNUSED tsdn_t *tsdn, UNUSED rtree_t *rtree,
225*1208bc7eSAndroid Build Coastguard Worker     rtree_leaf_elm_t *elm, bool dependent) {
226*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
227*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent);
228*1208bc7eSAndroid Build Coastguard Worker 	return rtree_leaf_elm_bits_szind_get(bits);
229*1208bc7eSAndroid Build Coastguard Worker #else
230*1208bc7eSAndroid Build Coastguard Worker 	return (szind_t)atomic_load_u(&elm->le_szind, dependent ? ATOMIC_RELAXED
231*1208bc7eSAndroid Build Coastguard Worker 	    : ATOMIC_ACQUIRE);
232*1208bc7eSAndroid Build Coastguard Worker #endif
233*1208bc7eSAndroid Build Coastguard Worker }
234*1208bc7eSAndroid Build Coastguard Worker 
235*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
rtree_leaf_elm_slab_read(UNUSED tsdn_t * tsdn,UNUSED rtree_t * rtree,rtree_leaf_elm_t * elm,bool dependent)236*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_slab_read(UNUSED tsdn_t *tsdn, UNUSED rtree_t *rtree,
237*1208bc7eSAndroid Build Coastguard Worker     rtree_leaf_elm_t *elm, bool dependent) {
238*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
239*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent);
240*1208bc7eSAndroid Build Coastguard Worker 	return rtree_leaf_elm_bits_slab_get(bits);
241*1208bc7eSAndroid Build Coastguard Worker #else
242*1208bc7eSAndroid Build Coastguard Worker 	return atomic_load_b(&elm->le_slab, dependent ? ATOMIC_RELAXED :
243*1208bc7eSAndroid Build Coastguard Worker 	    ATOMIC_ACQUIRE);
244*1208bc7eSAndroid Build Coastguard Worker #endif
245*1208bc7eSAndroid Build Coastguard Worker }
246*1208bc7eSAndroid Build Coastguard Worker 
247*1208bc7eSAndroid Build Coastguard Worker static inline void
rtree_leaf_elm_extent_write(UNUSED tsdn_t * tsdn,UNUSED rtree_t * rtree,rtree_leaf_elm_t * elm,extent_t * extent)248*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_extent_write(UNUSED tsdn_t *tsdn, UNUSED rtree_t *rtree,
249*1208bc7eSAndroid Build Coastguard Worker     rtree_leaf_elm_t *elm, extent_t *extent) {
250*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
251*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, true);
252*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t bits = ((uintptr_t)rtree_leaf_elm_bits_szind_get(old_bits) <<
253*1208bc7eSAndroid Build Coastguard Worker 	    LG_VADDR) | ((uintptr_t)extent & (((uintptr_t)0x1 << LG_VADDR) - 1))
254*1208bc7eSAndroid Build Coastguard Worker 	    | ((uintptr_t)rtree_leaf_elm_bits_slab_get(old_bits));
255*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_p(&elm->le_bits, (void *)bits, ATOMIC_RELEASE);
256*1208bc7eSAndroid Build Coastguard Worker #else
257*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_p(&elm->le_extent, extent, ATOMIC_RELEASE);
258*1208bc7eSAndroid Build Coastguard Worker #endif
259*1208bc7eSAndroid Build Coastguard Worker }
260*1208bc7eSAndroid Build Coastguard Worker 
261*1208bc7eSAndroid Build Coastguard Worker static inline void
rtree_leaf_elm_szind_write(UNUSED tsdn_t * tsdn,UNUSED rtree_t * rtree,rtree_leaf_elm_t * elm,szind_t szind)262*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_szind_write(UNUSED tsdn_t *tsdn, UNUSED rtree_t *rtree,
263*1208bc7eSAndroid Build Coastguard Worker     rtree_leaf_elm_t *elm, szind_t szind) {
264*1208bc7eSAndroid Build Coastguard Worker 	assert(szind <= NSIZES);
265*1208bc7eSAndroid Build Coastguard Worker 
266*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
267*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm,
268*1208bc7eSAndroid Build Coastguard Worker 	    true);
269*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t bits = ((uintptr_t)szind << LG_VADDR) |
270*1208bc7eSAndroid Build Coastguard Worker 	    ((uintptr_t)rtree_leaf_elm_bits_extent_get(old_bits) &
271*1208bc7eSAndroid Build Coastguard Worker 	    (((uintptr_t)0x1 << LG_VADDR) - 1)) |
272*1208bc7eSAndroid Build Coastguard Worker 	    ((uintptr_t)rtree_leaf_elm_bits_slab_get(old_bits));
273*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_p(&elm->le_bits, (void *)bits, ATOMIC_RELEASE);
274*1208bc7eSAndroid Build Coastguard Worker #else
275*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_u(&elm->le_szind, szind, ATOMIC_RELEASE);
276*1208bc7eSAndroid Build Coastguard Worker #endif
277*1208bc7eSAndroid Build Coastguard Worker }
278*1208bc7eSAndroid Build Coastguard Worker 
279*1208bc7eSAndroid Build Coastguard Worker static inline void
rtree_leaf_elm_slab_write(UNUSED tsdn_t * tsdn,UNUSED rtree_t * rtree,rtree_leaf_elm_t * elm,bool slab)280*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_slab_write(UNUSED tsdn_t *tsdn, UNUSED rtree_t *rtree,
281*1208bc7eSAndroid Build Coastguard Worker     rtree_leaf_elm_t *elm, bool slab) {
282*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
283*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t old_bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm,
284*1208bc7eSAndroid Build Coastguard Worker 	    true);
285*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t bits = ((uintptr_t)rtree_leaf_elm_bits_szind_get(old_bits) <<
286*1208bc7eSAndroid Build Coastguard Worker 	    LG_VADDR) | ((uintptr_t)rtree_leaf_elm_bits_extent_get(old_bits) &
287*1208bc7eSAndroid Build Coastguard Worker 	    (((uintptr_t)0x1 << LG_VADDR) - 1)) | ((uintptr_t)slab);
288*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_p(&elm->le_bits, (void *)bits, ATOMIC_RELEASE);
289*1208bc7eSAndroid Build Coastguard Worker #else
290*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_b(&elm->le_slab, slab, ATOMIC_RELEASE);
291*1208bc7eSAndroid Build Coastguard Worker #endif
292*1208bc7eSAndroid Build Coastguard Worker }
293*1208bc7eSAndroid Build Coastguard Worker 
294*1208bc7eSAndroid Build Coastguard Worker static inline void
rtree_leaf_elm_write(tsdn_t * tsdn,rtree_t * rtree,rtree_leaf_elm_t * elm,extent_t * extent,szind_t szind,bool slab)295*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_write(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *elm,
296*1208bc7eSAndroid Build Coastguard Worker     extent_t *extent, szind_t szind, bool slab) {
297*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
298*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t bits = ((uintptr_t)szind << LG_VADDR) |
299*1208bc7eSAndroid Build Coastguard Worker 	    ((uintptr_t)extent & (((uintptr_t)0x1 << LG_VADDR) - 1)) |
300*1208bc7eSAndroid Build Coastguard Worker 	    ((uintptr_t)slab);
301*1208bc7eSAndroid Build Coastguard Worker 	atomic_store_p(&elm->le_bits, (void *)bits, ATOMIC_RELEASE);
302*1208bc7eSAndroid Build Coastguard Worker #else
303*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_slab_write(tsdn, rtree, elm, slab);
304*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_szind_write(tsdn, rtree, elm, szind);
305*1208bc7eSAndroid Build Coastguard Worker 	/*
306*1208bc7eSAndroid Build Coastguard Worker 	 * Write extent last, since the element is atomically considered valid
307*1208bc7eSAndroid Build Coastguard Worker 	 * as soon as the extent field is non-NULL.
308*1208bc7eSAndroid Build Coastguard Worker 	 */
309*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_extent_write(tsdn, rtree, elm, extent);
310*1208bc7eSAndroid Build Coastguard Worker #endif
311*1208bc7eSAndroid Build Coastguard Worker }
312*1208bc7eSAndroid Build Coastguard Worker 
313*1208bc7eSAndroid Build Coastguard Worker static inline void
rtree_leaf_elm_szind_slab_update(tsdn_t * tsdn,rtree_t * rtree,rtree_leaf_elm_t * elm,szind_t szind,bool slab)314*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_szind_slab_update(tsdn_t *tsdn, rtree_t *rtree,
315*1208bc7eSAndroid Build Coastguard Worker     rtree_leaf_elm_t *elm, szind_t szind, bool slab) {
316*1208bc7eSAndroid Build Coastguard Worker 	assert(!slab || szind < NBINS);
317*1208bc7eSAndroid Build Coastguard Worker 
318*1208bc7eSAndroid Build Coastguard Worker 	/*
319*1208bc7eSAndroid Build Coastguard Worker 	 * The caller implicitly assures that it is the only writer to the szind
320*1208bc7eSAndroid Build Coastguard Worker 	 * and slab fields, and that the extent field cannot currently change.
321*1208bc7eSAndroid Build Coastguard Worker 	 */
322*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_slab_write(tsdn, rtree, elm, slab);
323*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_szind_write(tsdn, rtree, elm, szind);
324*1208bc7eSAndroid Build Coastguard Worker }
325*1208bc7eSAndroid Build Coastguard Worker 
326*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE rtree_leaf_elm_t *
rtree_leaf_elm_lookup(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,bool dependent,bool init_missing)327*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_lookup(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
328*1208bc7eSAndroid Build Coastguard Worker     uintptr_t key, bool dependent, bool init_missing) {
329*1208bc7eSAndroid Build Coastguard Worker 	assert(key != 0);
330*1208bc7eSAndroid Build Coastguard Worker 	assert(!dependent || !init_missing);
331*1208bc7eSAndroid Build Coastguard Worker 
332*1208bc7eSAndroid Build Coastguard Worker 	size_t slot = rtree_cache_direct_map(key);
333*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t leafkey = rtree_leafkey(key);
334*1208bc7eSAndroid Build Coastguard Worker 	assert(leafkey != RTREE_LEAFKEY_INVALID);
335*1208bc7eSAndroid Build Coastguard Worker 
336*1208bc7eSAndroid Build Coastguard Worker 	/* Fast path: L1 direct mapped cache. */
337*1208bc7eSAndroid Build Coastguard Worker 	if (likely(rtree_ctx->cache[slot].leafkey == leafkey)) {
338*1208bc7eSAndroid Build Coastguard Worker 		rtree_leaf_elm_t *leaf = rtree_ctx->cache[slot].leaf;
339*1208bc7eSAndroid Build Coastguard Worker 		/* ANDROID CHANGE: Bad pointers return NULL */
340*1208bc7eSAndroid Build Coastguard Worker 		/* assert(leaf != NULL); */
341*1208bc7eSAndroid Build Coastguard Worker 		if (leaf == NULL) {
342*1208bc7eSAndroid Build Coastguard Worker 			return NULL;
343*1208bc7eSAndroid Build Coastguard Worker 		}
344*1208bc7eSAndroid Build Coastguard Worker 		/* ANDROID END CHANGE */
345*1208bc7eSAndroid Build Coastguard Worker 		uintptr_t subkey = rtree_subkey(key, RTREE_HEIGHT-1);
346*1208bc7eSAndroid Build Coastguard Worker 		return &leaf[subkey];
347*1208bc7eSAndroid Build Coastguard Worker 	}
348*1208bc7eSAndroid Build Coastguard Worker 	/*
349*1208bc7eSAndroid Build Coastguard Worker 	 * Search the L2 LRU cache.  On hit, swap the matching element into the
350*1208bc7eSAndroid Build Coastguard Worker 	 * slot in L1 cache, and move the position in L2 up by 1.
351*1208bc7eSAndroid Build Coastguard Worker 	 */
352*1208bc7eSAndroid Build Coastguard Worker #define RTREE_CACHE_CHECK_L2(i) do {					\
353*1208bc7eSAndroid Build Coastguard Worker 	if (likely(rtree_ctx->l2_cache[i].leafkey == leafkey)) {	\
354*1208bc7eSAndroid Build Coastguard Worker 		rtree_leaf_elm_t *leaf = rtree_ctx->l2_cache[i].leaf;	\
355*1208bc7eSAndroid Build Coastguard Worker 		/* ANDROID CHANGE: Bad pointers return NULL */		\
356*1208bc7eSAndroid Build Coastguard Worker 		/* assert(leaf != NULL); */				\
357*1208bc7eSAndroid Build Coastguard Worker 		if (leaf == NULL) {					\
358*1208bc7eSAndroid Build Coastguard Worker 			return NULL;					\
359*1208bc7eSAndroid Build Coastguard Worker 		}							\
360*1208bc7eSAndroid Build Coastguard Worker 		/* ANDROID END CHANGE */				\
361*1208bc7eSAndroid Build Coastguard Worker 		if (i > 0) {						\
362*1208bc7eSAndroid Build Coastguard Worker 			/* Bubble up by one. */				\
363*1208bc7eSAndroid Build Coastguard Worker 			rtree_ctx->l2_cache[i].leafkey =		\
364*1208bc7eSAndroid Build Coastguard Worker 				rtree_ctx->l2_cache[i - 1].leafkey;	\
365*1208bc7eSAndroid Build Coastguard Worker 			rtree_ctx->l2_cache[i].leaf =			\
366*1208bc7eSAndroid Build Coastguard Worker 				rtree_ctx->l2_cache[i - 1].leaf;	\
367*1208bc7eSAndroid Build Coastguard Worker 			rtree_ctx->l2_cache[i - 1].leafkey =		\
368*1208bc7eSAndroid Build Coastguard Worker 			    rtree_ctx->cache[slot].leafkey;		\
369*1208bc7eSAndroid Build Coastguard Worker 			rtree_ctx->l2_cache[i - 1].leaf =		\
370*1208bc7eSAndroid Build Coastguard Worker 			    rtree_ctx->cache[slot].leaf;		\
371*1208bc7eSAndroid Build Coastguard Worker 		} else {						\
372*1208bc7eSAndroid Build Coastguard Worker 			rtree_ctx->l2_cache[0].leafkey =		\
373*1208bc7eSAndroid Build Coastguard Worker 			    rtree_ctx->cache[slot].leafkey;		\
374*1208bc7eSAndroid Build Coastguard Worker 			rtree_ctx->l2_cache[0].leaf =			\
375*1208bc7eSAndroid Build Coastguard Worker 			    rtree_ctx->cache[slot].leaf;		\
376*1208bc7eSAndroid Build Coastguard Worker 		}							\
377*1208bc7eSAndroid Build Coastguard Worker 		rtree_ctx->cache[slot].leafkey = leafkey;		\
378*1208bc7eSAndroid Build Coastguard Worker 		rtree_ctx->cache[slot].leaf = leaf;			\
379*1208bc7eSAndroid Build Coastguard Worker 		uintptr_t subkey = rtree_subkey(key, RTREE_HEIGHT-1);	\
380*1208bc7eSAndroid Build Coastguard Worker 		return &leaf[subkey];					\
381*1208bc7eSAndroid Build Coastguard Worker 	}								\
382*1208bc7eSAndroid Build Coastguard Worker } while (0)
383*1208bc7eSAndroid Build Coastguard Worker 	/* Check the first cache entry. */
384*1208bc7eSAndroid Build Coastguard Worker 	RTREE_CACHE_CHECK_L2(0);
385*1208bc7eSAndroid Build Coastguard Worker 	/* Search the remaining cache elements. */
386*1208bc7eSAndroid Build Coastguard Worker 	for (unsigned i = 1; i < RTREE_CTX_NCACHE_L2; i++) {
387*1208bc7eSAndroid Build Coastguard Worker 		RTREE_CACHE_CHECK_L2(i);
388*1208bc7eSAndroid Build Coastguard Worker 	}
389*1208bc7eSAndroid Build Coastguard Worker #undef RTREE_CACHE_CHECK_L2
390*1208bc7eSAndroid Build Coastguard Worker 
391*1208bc7eSAndroid Build Coastguard Worker 	return rtree_leaf_elm_lookup_hard(tsdn, rtree, rtree_ctx, key,
392*1208bc7eSAndroid Build Coastguard Worker 	    dependent, init_missing);
393*1208bc7eSAndroid Build Coastguard Worker }
394*1208bc7eSAndroid Build Coastguard Worker 
395*1208bc7eSAndroid Build Coastguard Worker static inline bool
rtree_write(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,extent_t * extent,szind_t szind,bool slab)396*1208bc7eSAndroid Build Coastguard Worker rtree_write(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key,
397*1208bc7eSAndroid Build Coastguard Worker     extent_t *extent, szind_t szind, bool slab) {
398*1208bc7eSAndroid Build Coastguard Worker 	/* Use rtree_clear() to set the extent to NULL. */
399*1208bc7eSAndroid Build Coastguard Worker 	assert(extent != NULL);
400*1208bc7eSAndroid Build Coastguard Worker 
401*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
402*1208bc7eSAndroid Build Coastguard Worker 	    key, false, true);
403*1208bc7eSAndroid Build Coastguard Worker 	if (elm == NULL) {
404*1208bc7eSAndroid Build Coastguard Worker 		return true;
405*1208bc7eSAndroid Build Coastguard Worker 	}
406*1208bc7eSAndroid Build Coastguard Worker 
407*1208bc7eSAndroid Build Coastguard Worker 	assert(rtree_leaf_elm_extent_read(tsdn, rtree, elm, false) == NULL);
408*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_write(tsdn, rtree, elm, extent, szind, slab);
409*1208bc7eSAndroid Build Coastguard Worker 
410*1208bc7eSAndroid Build Coastguard Worker 	return false;
411*1208bc7eSAndroid Build Coastguard Worker }
412*1208bc7eSAndroid Build Coastguard Worker 
413*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE rtree_leaf_elm_t *
rtree_read(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,bool dependent)414*1208bc7eSAndroid Build Coastguard Worker rtree_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx, uintptr_t key,
415*1208bc7eSAndroid Build Coastguard Worker     bool dependent) {
416*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree, rtree_ctx,
417*1208bc7eSAndroid Build Coastguard Worker 	    key, dependent, false);
418*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID CHANGE: Bad pointers return NULL */
419*1208bc7eSAndroid Build Coastguard Worker 	/* if (!dependent && elm == NULL) { */
420*1208bc7eSAndroid Build Coastguard Worker 	if (elm == NULL) {
421*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID END CHANGE */
422*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
423*1208bc7eSAndroid Build Coastguard Worker 	}
424*1208bc7eSAndroid Build Coastguard Worker 	assert(elm != NULL);
425*1208bc7eSAndroid Build Coastguard Worker 	return elm;
426*1208bc7eSAndroid Build Coastguard Worker }
427*1208bc7eSAndroid Build Coastguard Worker 
428*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE extent_t *
rtree_extent_read(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,bool dependent)429*1208bc7eSAndroid Build Coastguard Worker rtree_extent_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
430*1208bc7eSAndroid Build Coastguard Worker     uintptr_t key, bool dependent) {
431*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key,
432*1208bc7eSAndroid Build Coastguard Worker 	    dependent);
433*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID CHANGE: Bad pointers return NULL */
434*1208bc7eSAndroid Build Coastguard Worker 	/* if (!dependent && elm == NULL) { */
435*1208bc7eSAndroid Build Coastguard Worker 	if (elm == NULL) {
436*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID END CHANGE */
437*1208bc7eSAndroid Build Coastguard Worker 		return NULL;
438*1208bc7eSAndroid Build Coastguard Worker 	}
439*1208bc7eSAndroid Build Coastguard Worker 	return rtree_leaf_elm_extent_read(tsdn, rtree, elm, dependent);
440*1208bc7eSAndroid Build Coastguard Worker }
441*1208bc7eSAndroid Build Coastguard Worker 
442*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE szind_t
rtree_szind_read(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,bool dependent)443*1208bc7eSAndroid Build Coastguard Worker rtree_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
444*1208bc7eSAndroid Build Coastguard Worker     uintptr_t key, bool dependent) {
445*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key,
446*1208bc7eSAndroid Build Coastguard Worker 	    dependent);
447*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID CHANGE: Bad pointers return NULL */
448*1208bc7eSAndroid Build Coastguard Worker 	/* if (!dependent && elm == NULL) { */
449*1208bc7eSAndroid Build Coastguard Worker 	if (elm == NULL) {
450*1208bc7eSAndroid Build Coastguard Worker 		return NSIZES;
451*1208bc7eSAndroid Build Coastguard Worker 	}
452*1208bc7eSAndroid Build Coastguard Worker 	return rtree_leaf_elm_szind_read(tsdn, rtree, elm, dependent);
453*1208bc7eSAndroid Build Coastguard Worker }
454*1208bc7eSAndroid Build Coastguard Worker 
455*1208bc7eSAndroid Build Coastguard Worker /*
456*1208bc7eSAndroid Build Coastguard Worker  * rtree_slab_read() is intentionally omitted because slab is always read in
457*1208bc7eSAndroid Build Coastguard Worker  * conjunction with szind, which makes rtree_szind_slab_read() a better choice.
458*1208bc7eSAndroid Build Coastguard Worker  */
459*1208bc7eSAndroid Build Coastguard Worker 
460*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
rtree_extent_szind_read(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,bool dependent,extent_t ** r_extent,szind_t * r_szind)461*1208bc7eSAndroid Build Coastguard Worker rtree_extent_szind_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
462*1208bc7eSAndroid Build Coastguard Worker     uintptr_t key, bool dependent, extent_t **r_extent, szind_t *r_szind) {
463*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key,
464*1208bc7eSAndroid Build Coastguard Worker 	    dependent);
465*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID CHANGE: Bad pointers return NULL */
466*1208bc7eSAndroid Build Coastguard Worker 	/* if (!dependent && elm == NULL) { */
467*1208bc7eSAndroid Build Coastguard Worker 	if (elm == NULL) {
468*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID END CHANGE */
469*1208bc7eSAndroid Build Coastguard Worker 		return true;
470*1208bc7eSAndroid Build Coastguard Worker 	}
471*1208bc7eSAndroid Build Coastguard Worker 	*r_extent = rtree_leaf_elm_extent_read(tsdn, rtree, elm, dependent);
472*1208bc7eSAndroid Build Coastguard Worker 	*r_szind = rtree_leaf_elm_szind_read(tsdn, rtree, elm, dependent);
473*1208bc7eSAndroid Build Coastguard Worker 	return false;
474*1208bc7eSAndroid Build Coastguard Worker }
475*1208bc7eSAndroid Build Coastguard Worker 
476*1208bc7eSAndroid Build Coastguard Worker JEMALLOC_ALWAYS_INLINE bool
rtree_szind_slab_read(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,bool dependent,szind_t * r_szind,bool * r_slab)477*1208bc7eSAndroid Build Coastguard Worker rtree_szind_slab_read(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
478*1208bc7eSAndroid Build Coastguard Worker     uintptr_t key, bool dependent, szind_t *r_szind, bool *r_slab) {
479*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key,
480*1208bc7eSAndroid Build Coastguard Worker 	    dependent);
481*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID CHANGE: Bad pointers return NULL */
482*1208bc7eSAndroid Build Coastguard Worker 	/* if (!dependent && elm == NULL) { */
483*1208bc7eSAndroid Build Coastguard Worker 	if (elm == NULL) {
484*1208bc7eSAndroid Build Coastguard Worker 	/* ANDROID END CHANGE */
485*1208bc7eSAndroid Build Coastguard Worker 		return true;
486*1208bc7eSAndroid Build Coastguard Worker 	}
487*1208bc7eSAndroid Build Coastguard Worker #ifdef RTREE_LEAF_COMPACT
488*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t bits = rtree_leaf_elm_bits_read(tsdn, rtree, elm, dependent);
489*1208bc7eSAndroid Build Coastguard Worker 	*r_szind = rtree_leaf_elm_bits_szind_get(bits);
490*1208bc7eSAndroid Build Coastguard Worker 	*r_slab = rtree_leaf_elm_bits_slab_get(bits);
491*1208bc7eSAndroid Build Coastguard Worker #else
492*1208bc7eSAndroid Build Coastguard Worker 	*r_szind = rtree_leaf_elm_szind_read(tsdn, rtree, elm, dependent);
493*1208bc7eSAndroid Build Coastguard Worker 	*r_slab = rtree_leaf_elm_slab_read(tsdn, rtree, elm, dependent);
494*1208bc7eSAndroid Build Coastguard Worker #endif
495*1208bc7eSAndroid Build Coastguard Worker 	return false;
496*1208bc7eSAndroid Build Coastguard Worker }
497*1208bc7eSAndroid Build Coastguard Worker 
498*1208bc7eSAndroid Build Coastguard Worker static inline void
rtree_szind_slab_update(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,szind_t szind,bool slab)499*1208bc7eSAndroid Build Coastguard Worker rtree_szind_slab_update(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
500*1208bc7eSAndroid Build Coastguard Worker     uintptr_t key, szind_t szind, bool slab) {
501*1208bc7eSAndroid Build Coastguard Worker 	assert(!slab || szind < NBINS);
502*1208bc7eSAndroid Build Coastguard Worker 
503*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, true);
504*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_szind_slab_update(tsdn, rtree, elm, szind, slab);
505*1208bc7eSAndroid Build Coastguard Worker }
506*1208bc7eSAndroid Build Coastguard Worker 
507*1208bc7eSAndroid Build Coastguard Worker static inline void
rtree_clear(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key)508*1208bc7eSAndroid Build Coastguard Worker rtree_clear(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
509*1208bc7eSAndroid Build Coastguard Worker     uintptr_t key) {
510*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *elm = rtree_read(tsdn, rtree, rtree_ctx, key, true);
511*1208bc7eSAndroid Build Coastguard Worker 	assert(rtree_leaf_elm_extent_read(tsdn, rtree, elm, false) !=
512*1208bc7eSAndroid Build Coastguard Worker 	    NULL);
513*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_write(tsdn, rtree, elm, NULL, NSIZES, false);
514*1208bc7eSAndroid Build Coastguard Worker }
515*1208bc7eSAndroid Build Coastguard Worker 
516*1208bc7eSAndroid Build Coastguard Worker #endif /* JEMALLOC_INTERNAL_RTREE_H */
517