1*1208bc7eSAndroid Build Coastguard Worker #define JEMALLOC_RTREE_C_
2*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_preamble.h"
3*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/jemalloc_internal_includes.h"
4*1208bc7eSAndroid Build Coastguard Worker
5*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/assert.h"
6*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/mutex.h"
7*1208bc7eSAndroid Build Coastguard Worker
8*1208bc7eSAndroid Build Coastguard Worker /*
9*1208bc7eSAndroid Build Coastguard Worker * Only the most significant bits of keys passed to rtree_{read,write}() are
10*1208bc7eSAndroid Build Coastguard Worker * used.
11*1208bc7eSAndroid Build Coastguard Worker */
12*1208bc7eSAndroid Build Coastguard Worker bool
rtree_new(rtree_t * rtree,bool zeroed)13*1208bc7eSAndroid Build Coastguard Worker rtree_new(rtree_t *rtree, bool zeroed) {
14*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_JET
15*1208bc7eSAndroid Build Coastguard Worker if (!zeroed) {
16*1208bc7eSAndroid Build Coastguard Worker memset(rtree, 0, sizeof(rtree_t)); /* Clear root. */
17*1208bc7eSAndroid Build Coastguard Worker }
18*1208bc7eSAndroid Build Coastguard Worker #else
19*1208bc7eSAndroid Build Coastguard Worker assert(zeroed);
20*1208bc7eSAndroid Build Coastguard Worker #endif
21*1208bc7eSAndroid Build Coastguard Worker
22*1208bc7eSAndroid Build Coastguard Worker if (malloc_mutex_init(&rtree->init_lock, "rtree", WITNESS_RANK_RTREE,
23*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_rank_exclusive)) {
24*1208bc7eSAndroid Build Coastguard Worker return true;
25*1208bc7eSAndroid Build Coastguard Worker }
26*1208bc7eSAndroid Build Coastguard Worker
27*1208bc7eSAndroid Build Coastguard Worker return false;
28*1208bc7eSAndroid Build Coastguard Worker }
29*1208bc7eSAndroid Build Coastguard Worker
30*1208bc7eSAndroid Build Coastguard Worker static rtree_node_elm_t *
rtree_node_alloc_impl(tsdn_t * tsdn,rtree_t * rtree,size_t nelms)31*1208bc7eSAndroid Build Coastguard Worker rtree_node_alloc_impl(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) {
32*1208bc7eSAndroid Build Coastguard Worker return (rtree_node_elm_t *)base_alloc(tsdn, b0get(), nelms *
33*1208bc7eSAndroid Build Coastguard Worker sizeof(rtree_node_elm_t), CACHELINE);
34*1208bc7eSAndroid Build Coastguard Worker }
35*1208bc7eSAndroid Build Coastguard Worker rtree_node_alloc_t *JET_MUTABLE rtree_node_alloc = rtree_node_alloc_impl;
36*1208bc7eSAndroid Build Coastguard Worker
37*1208bc7eSAndroid Build Coastguard Worker static void
rtree_node_dalloc_impl(tsdn_t * tsdn,rtree_t * rtree,rtree_node_elm_t * node)38*1208bc7eSAndroid Build Coastguard Worker rtree_node_dalloc_impl(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *node) {
39*1208bc7eSAndroid Build Coastguard Worker /* Nodes are never deleted during normal operation. */
40*1208bc7eSAndroid Build Coastguard Worker not_reached();
41*1208bc7eSAndroid Build Coastguard Worker }
42*1208bc7eSAndroid Build Coastguard Worker UNUSED rtree_node_dalloc_t *JET_MUTABLE rtree_node_dalloc =
43*1208bc7eSAndroid Build Coastguard Worker rtree_node_dalloc_impl;
44*1208bc7eSAndroid Build Coastguard Worker
45*1208bc7eSAndroid Build Coastguard Worker static rtree_leaf_elm_t *
rtree_leaf_alloc_impl(tsdn_t * tsdn,rtree_t * rtree,size_t nelms)46*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_alloc_impl(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) {
47*1208bc7eSAndroid Build Coastguard Worker return (rtree_leaf_elm_t *)base_alloc(tsdn, b0get(), nelms *
48*1208bc7eSAndroid Build Coastguard Worker sizeof(rtree_leaf_elm_t), CACHELINE);
49*1208bc7eSAndroid Build Coastguard Worker }
50*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_alloc_t *JET_MUTABLE rtree_leaf_alloc = rtree_leaf_alloc_impl;
51*1208bc7eSAndroid Build Coastguard Worker
52*1208bc7eSAndroid Build Coastguard Worker static void
rtree_leaf_dalloc_impl(tsdn_t * tsdn,rtree_t * rtree,rtree_leaf_elm_t * leaf)53*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_dalloc_impl(tsdn_t *tsdn, rtree_t *rtree, rtree_leaf_elm_t *leaf) {
54*1208bc7eSAndroid Build Coastguard Worker /* Leaves are never deleted during normal operation. */
55*1208bc7eSAndroid Build Coastguard Worker not_reached();
56*1208bc7eSAndroid Build Coastguard Worker }
57*1208bc7eSAndroid Build Coastguard Worker UNUSED rtree_leaf_dalloc_t *JET_MUTABLE rtree_leaf_dalloc =
58*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_dalloc_impl;
59*1208bc7eSAndroid Build Coastguard Worker
60*1208bc7eSAndroid Build Coastguard Worker #ifdef JEMALLOC_JET
61*1208bc7eSAndroid Build Coastguard Worker # if RTREE_HEIGHT > 1
62*1208bc7eSAndroid Build Coastguard Worker static void
rtree_delete_subtree(tsdn_t * tsdn,rtree_t * rtree,rtree_node_elm_t * subtree,unsigned level)63*1208bc7eSAndroid Build Coastguard Worker rtree_delete_subtree(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *subtree,
64*1208bc7eSAndroid Build Coastguard Worker unsigned level) {
65*1208bc7eSAndroid Build Coastguard Worker size_t nchildren = ZU(1) << rtree_levels[level].bits;
66*1208bc7eSAndroid Build Coastguard Worker if (level + 2 < RTREE_HEIGHT) {
67*1208bc7eSAndroid Build Coastguard Worker for (size_t i = 0; i < nchildren; i++) {
68*1208bc7eSAndroid Build Coastguard Worker rtree_node_elm_t *node =
69*1208bc7eSAndroid Build Coastguard Worker (rtree_node_elm_t *)atomic_load_p(&subtree[i].child,
70*1208bc7eSAndroid Build Coastguard Worker ATOMIC_RELAXED);
71*1208bc7eSAndroid Build Coastguard Worker if (node != NULL) {
72*1208bc7eSAndroid Build Coastguard Worker rtree_delete_subtree(tsdn, rtree, node, level +
73*1208bc7eSAndroid Build Coastguard Worker 1);
74*1208bc7eSAndroid Build Coastguard Worker }
75*1208bc7eSAndroid Build Coastguard Worker }
76*1208bc7eSAndroid Build Coastguard Worker } else {
77*1208bc7eSAndroid Build Coastguard Worker for (size_t i = 0; i < nchildren; i++) {
78*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_t *leaf =
79*1208bc7eSAndroid Build Coastguard Worker (rtree_leaf_elm_t *)atomic_load_p(&subtree[i].child,
80*1208bc7eSAndroid Build Coastguard Worker ATOMIC_RELAXED);
81*1208bc7eSAndroid Build Coastguard Worker if (leaf != NULL) {
82*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_dalloc(tsdn, rtree, leaf);
83*1208bc7eSAndroid Build Coastguard Worker }
84*1208bc7eSAndroid Build Coastguard Worker }
85*1208bc7eSAndroid Build Coastguard Worker }
86*1208bc7eSAndroid Build Coastguard Worker
87*1208bc7eSAndroid Build Coastguard Worker if (subtree != rtree->root) {
88*1208bc7eSAndroid Build Coastguard Worker rtree_node_dalloc(tsdn, rtree, subtree);
89*1208bc7eSAndroid Build Coastguard Worker }
90*1208bc7eSAndroid Build Coastguard Worker }
91*1208bc7eSAndroid Build Coastguard Worker # endif
92*1208bc7eSAndroid Build Coastguard Worker
93*1208bc7eSAndroid Build Coastguard Worker void
rtree_delete(tsdn_t * tsdn,rtree_t * rtree)94*1208bc7eSAndroid Build Coastguard Worker rtree_delete(tsdn_t *tsdn, rtree_t *rtree) {
95*1208bc7eSAndroid Build Coastguard Worker # if RTREE_HEIGHT > 1
96*1208bc7eSAndroid Build Coastguard Worker rtree_delete_subtree(tsdn, rtree, rtree->root, 0);
97*1208bc7eSAndroid Build Coastguard Worker # endif
98*1208bc7eSAndroid Build Coastguard Worker }
99*1208bc7eSAndroid Build Coastguard Worker #endif
100*1208bc7eSAndroid Build Coastguard Worker
101*1208bc7eSAndroid Build Coastguard Worker static rtree_node_elm_t *
rtree_node_init(tsdn_t * tsdn,rtree_t * rtree,unsigned level,atomic_p_t * elmp)102*1208bc7eSAndroid Build Coastguard Worker rtree_node_init(tsdn_t *tsdn, rtree_t *rtree, unsigned level,
103*1208bc7eSAndroid Build Coastguard Worker atomic_p_t *elmp) {
104*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(tsdn, &rtree->init_lock);
105*1208bc7eSAndroid Build Coastguard Worker /*
106*1208bc7eSAndroid Build Coastguard Worker * If *elmp is non-null, then it was initialized with the init lock
107*1208bc7eSAndroid Build Coastguard Worker * held, so we can get by with 'relaxed' here.
108*1208bc7eSAndroid Build Coastguard Worker */
109*1208bc7eSAndroid Build Coastguard Worker rtree_node_elm_t *node = atomic_load_p(elmp, ATOMIC_RELAXED);
110*1208bc7eSAndroid Build Coastguard Worker if (node == NULL) {
111*1208bc7eSAndroid Build Coastguard Worker node = rtree_node_alloc(tsdn, rtree, ZU(1) <<
112*1208bc7eSAndroid Build Coastguard Worker rtree_levels[level].bits);
113*1208bc7eSAndroid Build Coastguard Worker if (node == NULL) {
114*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsdn, &rtree->init_lock);
115*1208bc7eSAndroid Build Coastguard Worker return NULL;
116*1208bc7eSAndroid Build Coastguard Worker }
117*1208bc7eSAndroid Build Coastguard Worker /*
118*1208bc7eSAndroid Build Coastguard Worker * Even though we hold the lock, a later reader might not; we
119*1208bc7eSAndroid Build Coastguard Worker * need release semantics.
120*1208bc7eSAndroid Build Coastguard Worker */
121*1208bc7eSAndroid Build Coastguard Worker atomic_store_p(elmp, node, ATOMIC_RELEASE);
122*1208bc7eSAndroid Build Coastguard Worker }
123*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsdn, &rtree->init_lock);
124*1208bc7eSAndroid Build Coastguard Worker
125*1208bc7eSAndroid Build Coastguard Worker return node;
126*1208bc7eSAndroid Build Coastguard Worker }
127*1208bc7eSAndroid Build Coastguard Worker
128*1208bc7eSAndroid Build Coastguard Worker static rtree_leaf_elm_t *
rtree_leaf_init(tsdn_t * tsdn,rtree_t * rtree,atomic_p_t * elmp)129*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_init(tsdn_t *tsdn, rtree_t *rtree, atomic_p_t *elmp) {
130*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_lock(tsdn, &rtree->init_lock);
131*1208bc7eSAndroid Build Coastguard Worker /*
132*1208bc7eSAndroid Build Coastguard Worker * If *elmp is non-null, then it was initialized with the init lock
133*1208bc7eSAndroid Build Coastguard Worker * held, so we can get by with 'relaxed' here.
134*1208bc7eSAndroid Build Coastguard Worker */
135*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_t *leaf = atomic_load_p(elmp, ATOMIC_RELAXED);
136*1208bc7eSAndroid Build Coastguard Worker if (leaf == NULL) {
137*1208bc7eSAndroid Build Coastguard Worker leaf = rtree_leaf_alloc(tsdn, rtree, ZU(1) <<
138*1208bc7eSAndroid Build Coastguard Worker rtree_levels[RTREE_HEIGHT-1].bits);
139*1208bc7eSAndroid Build Coastguard Worker if (leaf == NULL) {
140*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsdn, &rtree->init_lock);
141*1208bc7eSAndroid Build Coastguard Worker return NULL;
142*1208bc7eSAndroid Build Coastguard Worker }
143*1208bc7eSAndroid Build Coastguard Worker /*
144*1208bc7eSAndroid Build Coastguard Worker * Even though we hold the lock, a later reader might not; we
145*1208bc7eSAndroid Build Coastguard Worker * need release semantics.
146*1208bc7eSAndroid Build Coastguard Worker */
147*1208bc7eSAndroid Build Coastguard Worker atomic_store_p(elmp, leaf, ATOMIC_RELEASE);
148*1208bc7eSAndroid Build Coastguard Worker }
149*1208bc7eSAndroid Build Coastguard Worker malloc_mutex_unlock(tsdn, &rtree->init_lock);
150*1208bc7eSAndroid Build Coastguard Worker
151*1208bc7eSAndroid Build Coastguard Worker return leaf;
152*1208bc7eSAndroid Build Coastguard Worker }
153*1208bc7eSAndroid Build Coastguard Worker
154*1208bc7eSAndroid Build Coastguard Worker static bool
rtree_node_valid(rtree_node_elm_t * node)155*1208bc7eSAndroid Build Coastguard Worker rtree_node_valid(rtree_node_elm_t *node) {
156*1208bc7eSAndroid Build Coastguard Worker return ((uintptr_t)node != (uintptr_t)0);
157*1208bc7eSAndroid Build Coastguard Worker }
158*1208bc7eSAndroid Build Coastguard Worker
159*1208bc7eSAndroid Build Coastguard Worker static bool
rtree_leaf_valid(rtree_leaf_elm_t * leaf)160*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_valid(rtree_leaf_elm_t *leaf) {
161*1208bc7eSAndroid Build Coastguard Worker return ((uintptr_t)leaf != (uintptr_t)0);
162*1208bc7eSAndroid Build Coastguard Worker }
163*1208bc7eSAndroid Build Coastguard Worker
164*1208bc7eSAndroid Build Coastguard Worker static rtree_node_elm_t *
rtree_child_node_tryread(rtree_node_elm_t * elm,bool dependent)165*1208bc7eSAndroid Build Coastguard Worker rtree_child_node_tryread(rtree_node_elm_t *elm, bool dependent) {
166*1208bc7eSAndroid Build Coastguard Worker rtree_node_elm_t *node;
167*1208bc7eSAndroid Build Coastguard Worker
168*1208bc7eSAndroid Build Coastguard Worker if (dependent) {
169*1208bc7eSAndroid Build Coastguard Worker node = (rtree_node_elm_t *)atomic_load_p(&elm->child,
170*1208bc7eSAndroid Build Coastguard Worker ATOMIC_RELAXED);
171*1208bc7eSAndroid Build Coastguard Worker } else {
172*1208bc7eSAndroid Build Coastguard Worker node = (rtree_node_elm_t *)atomic_load_p(&elm->child,
173*1208bc7eSAndroid Build Coastguard Worker ATOMIC_ACQUIRE);
174*1208bc7eSAndroid Build Coastguard Worker }
175*1208bc7eSAndroid Build Coastguard Worker
176*1208bc7eSAndroid Build Coastguard Worker assert(!dependent || node != NULL);
177*1208bc7eSAndroid Build Coastguard Worker return node;
178*1208bc7eSAndroid Build Coastguard Worker }
179*1208bc7eSAndroid Build Coastguard Worker
180*1208bc7eSAndroid Build Coastguard Worker static rtree_node_elm_t *
rtree_child_node_read(tsdn_t * tsdn,rtree_t * rtree,rtree_node_elm_t * elm,unsigned level,bool dependent)181*1208bc7eSAndroid Build Coastguard Worker rtree_child_node_read(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *elm,
182*1208bc7eSAndroid Build Coastguard Worker unsigned level, bool dependent) {
183*1208bc7eSAndroid Build Coastguard Worker rtree_node_elm_t *node;
184*1208bc7eSAndroid Build Coastguard Worker
185*1208bc7eSAndroid Build Coastguard Worker node = rtree_child_node_tryread(elm, dependent);
186*1208bc7eSAndroid Build Coastguard Worker if (!dependent && unlikely(!rtree_node_valid(node))) {
187*1208bc7eSAndroid Build Coastguard Worker node = rtree_node_init(tsdn, rtree, level + 1, &elm->child);
188*1208bc7eSAndroid Build Coastguard Worker }
189*1208bc7eSAndroid Build Coastguard Worker assert(!dependent || node != NULL);
190*1208bc7eSAndroid Build Coastguard Worker return node;
191*1208bc7eSAndroid Build Coastguard Worker }
192*1208bc7eSAndroid Build Coastguard Worker
193*1208bc7eSAndroid Build Coastguard Worker static rtree_leaf_elm_t *
rtree_child_leaf_tryread(rtree_node_elm_t * elm,bool dependent)194*1208bc7eSAndroid Build Coastguard Worker rtree_child_leaf_tryread(rtree_node_elm_t *elm, bool dependent) {
195*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_t *leaf;
196*1208bc7eSAndroid Build Coastguard Worker
197*1208bc7eSAndroid Build Coastguard Worker if (dependent) {
198*1208bc7eSAndroid Build Coastguard Worker leaf = (rtree_leaf_elm_t *)atomic_load_p(&elm->child,
199*1208bc7eSAndroid Build Coastguard Worker ATOMIC_RELAXED);
200*1208bc7eSAndroid Build Coastguard Worker } else {
201*1208bc7eSAndroid Build Coastguard Worker leaf = (rtree_leaf_elm_t *)atomic_load_p(&elm->child,
202*1208bc7eSAndroid Build Coastguard Worker ATOMIC_ACQUIRE);
203*1208bc7eSAndroid Build Coastguard Worker }
204*1208bc7eSAndroid Build Coastguard Worker
205*1208bc7eSAndroid Build Coastguard Worker assert(!dependent || leaf != NULL);
206*1208bc7eSAndroid Build Coastguard Worker return leaf;
207*1208bc7eSAndroid Build Coastguard Worker }
208*1208bc7eSAndroid Build Coastguard Worker
209*1208bc7eSAndroid Build Coastguard Worker static rtree_leaf_elm_t *
rtree_child_leaf_read(tsdn_t * tsdn,rtree_t * rtree,rtree_node_elm_t * elm,unsigned level,bool dependent)210*1208bc7eSAndroid Build Coastguard Worker rtree_child_leaf_read(tsdn_t *tsdn, rtree_t *rtree, rtree_node_elm_t *elm,
211*1208bc7eSAndroid Build Coastguard Worker unsigned level, bool dependent) {
212*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_t *leaf;
213*1208bc7eSAndroid Build Coastguard Worker
214*1208bc7eSAndroid Build Coastguard Worker leaf = rtree_child_leaf_tryread(elm, dependent);
215*1208bc7eSAndroid Build Coastguard Worker if (!dependent && unlikely(!rtree_leaf_valid(leaf))) {
216*1208bc7eSAndroid Build Coastguard Worker leaf = rtree_leaf_init(tsdn, rtree, &elm->child);
217*1208bc7eSAndroid Build Coastguard Worker }
218*1208bc7eSAndroid Build Coastguard Worker assert(!dependent || leaf != NULL);
219*1208bc7eSAndroid Build Coastguard Worker return leaf;
220*1208bc7eSAndroid Build Coastguard Worker }
221*1208bc7eSAndroid Build Coastguard Worker
222*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_t *
rtree_leaf_elm_lookup_hard(tsdn_t * tsdn,rtree_t * rtree,rtree_ctx_t * rtree_ctx,uintptr_t key,bool dependent,bool init_missing)223*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_lookup_hard(tsdn_t *tsdn, rtree_t *rtree, rtree_ctx_t *rtree_ctx,
224*1208bc7eSAndroid Build Coastguard Worker uintptr_t key, bool dependent, bool init_missing) {
225*1208bc7eSAndroid Build Coastguard Worker rtree_node_elm_t *node;
226*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_elm_t *leaf;
227*1208bc7eSAndroid Build Coastguard Worker #if RTREE_HEIGHT > 1
228*1208bc7eSAndroid Build Coastguard Worker node = rtree->root;
229*1208bc7eSAndroid Build Coastguard Worker #else
230*1208bc7eSAndroid Build Coastguard Worker leaf = rtree->root;
231*1208bc7eSAndroid Build Coastguard Worker #endif
232*1208bc7eSAndroid Build Coastguard Worker
233*1208bc7eSAndroid Build Coastguard Worker if (config_debug) {
234*1208bc7eSAndroid Build Coastguard Worker uintptr_t leafkey = rtree_leafkey(key);
235*1208bc7eSAndroid Build Coastguard Worker for (unsigned i = 0; i < RTREE_CTX_NCACHE; i++) {
236*1208bc7eSAndroid Build Coastguard Worker assert(rtree_ctx->cache[i].leafkey != leafkey);
237*1208bc7eSAndroid Build Coastguard Worker }
238*1208bc7eSAndroid Build Coastguard Worker for (unsigned i = 0; i < RTREE_CTX_NCACHE_L2; i++) {
239*1208bc7eSAndroid Build Coastguard Worker assert(rtree_ctx->l2_cache[i].leafkey != leafkey);
240*1208bc7eSAndroid Build Coastguard Worker }
241*1208bc7eSAndroid Build Coastguard Worker }
242*1208bc7eSAndroid Build Coastguard Worker
243*1208bc7eSAndroid Build Coastguard Worker #define RTREE_GET_CHILD(level) { \
244*1208bc7eSAndroid Build Coastguard Worker assert(level < RTREE_HEIGHT-1); \
245*1208bc7eSAndroid Build Coastguard Worker /* ANDROID CHANGE: Bad pointers return NULL */ \
246*1208bc7eSAndroid Build Coastguard Worker /* if (level != 0 && !dependent && */ \
247*1208bc7eSAndroid Build Coastguard Worker /* unlikely(!rtree_node_valid(node))) { */ \
248*1208bc7eSAndroid Build Coastguard Worker if (unlikely(!rtree_node_valid(node))) { \
249*1208bc7eSAndroid Build Coastguard Worker /* ANDROID END CHANGE */ \
250*1208bc7eSAndroid Build Coastguard Worker return NULL; \
251*1208bc7eSAndroid Build Coastguard Worker } \
252*1208bc7eSAndroid Build Coastguard Worker uintptr_t subkey = rtree_subkey(key, level); \
253*1208bc7eSAndroid Build Coastguard Worker if (level + 2 < RTREE_HEIGHT) { \
254*1208bc7eSAndroid Build Coastguard Worker node = init_missing ? \
255*1208bc7eSAndroid Build Coastguard Worker rtree_child_node_read(tsdn, rtree, \
256*1208bc7eSAndroid Build Coastguard Worker &node[subkey], level, dependent) : \
257*1208bc7eSAndroid Build Coastguard Worker rtree_child_node_tryread(&node[subkey], \
258*1208bc7eSAndroid Build Coastguard Worker dependent); \
259*1208bc7eSAndroid Build Coastguard Worker } else { \
260*1208bc7eSAndroid Build Coastguard Worker leaf = init_missing ? \
261*1208bc7eSAndroid Build Coastguard Worker rtree_child_leaf_read(tsdn, rtree, \
262*1208bc7eSAndroid Build Coastguard Worker &node[subkey], level, dependent) : \
263*1208bc7eSAndroid Build Coastguard Worker rtree_child_leaf_tryread(&node[subkey], \
264*1208bc7eSAndroid Build Coastguard Worker dependent); \
265*1208bc7eSAndroid Build Coastguard Worker } \
266*1208bc7eSAndroid Build Coastguard Worker }
267*1208bc7eSAndroid Build Coastguard Worker /*
268*1208bc7eSAndroid Build Coastguard Worker * Cache replacement upon hard lookup (i.e. L1 & L2 rtree cache miss):
269*1208bc7eSAndroid Build Coastguard Worker * (1) evict last entry in L2 cache; (2) move the collision slot from L1
270*1208bc7eSAndroid Build Coastguard Worker * cache down to L2; and 3) fill L1.
271*1208bc7eSAndroid Build Coastguard Worker */
272*1208bc7eSAndroid Build Coastguard Worker #define RTREE_GET_LEAF(level) { \
273*1208bc7eSAndroid Build Coastguard Worker assert(level == RTREE_HEIGHT-1); \
274*1208bc7eSAndroid Build Coastguard Worker /* ANDROID CHANGE: Bad pointers return NULL */ \
275*1208bc7eSAndroid Build Coastguard Worker /* if (!dependent && unlikely(!rtree_leaf_valid(leaf))) {*/ \
276*1208bc7eSAndroid Build Coastguard Worker if (unlikely(!rtree_leaf_valid(leaf))) { \
277*1208bc7eSAndroid Build Coastguard Worker /* ANDROID END CHANGE */ \
278*1208bc7eSAndroid Build Coastguard Worker return NULL; \
279*1208bc7eSAndroid Build Coastguard Worker } \
280*1208bc7eSAndroid Build Coastguard Worker if (RTREE_CTX_NCACHE_L2 > 1) { \
281*1208bc7eSAndroid Build Coastguard Worker memmove(&rtree_ctx->l2_cache[1], \
282*1208bc7eSAndroid Build Coastguard Worker &rtree_ctx->l2_cache[0], \
283*1208bc7eSAndroid Build Coastguard Worker sizeof(rtree_ctx_cache_elm_t) * \
284*1208bc7eSAndroid Build Coastguard Worker (RTREE_CTX_NCACHE_L2 - 1)); \
285*1208bc7eSAndroid Build Coastguard Worker } \
286*1208bc7eSAndroid Build Coastguard Worker size_t slot = rtree_cache_direct_map(key); \
287*1208bc7eSAndroid Build Coastguard Worker rtree_ctx->l2_cache[0].leafkey = \
288*1208bc7eSAndroid Build Coastguard Worker rtree_ctx->cache[slot].leafkey; \
289*1208bc7eSAndroid Build Coastguard Worker rtree_ctx->l2_cache[0].leaf = \
290*1208bc7eSAndroid Build Coastguard Worker rtree_ctx->cache[slot].leaf; \
291*1208bc7eSAndroid Build Coastguard Worker uintptr_t leafkey = rtree_leafkey(key); \
292*1208bc7eSAndroid Build Coastguard Worker rtree_ctx->cache[slot].leafkey = leafkey; \
293*1208bc7eSAndroid Build Coastguard Worker rtree_ctx->cache[slot].leaf = leaf; \
294*1208bc7eSAndroid Build Coastguard Worker uintptr_t subkey = rtree_subkey(key, level); \
295*1208bc7eSAndroid Build Coastguard Worker return &leaf[subkey]; \
296*1208bc7eSAndroid Build Coastguard Worker }
297*1208bc7eSAndroid Build Coastguard Worker if (RTREE_HEIGHT > 1) {
298*1208bc7eSAndroid Build Coastguard Worker RTREE_GET_CHILD(0)
299*1208bc7eSAndroid Build Coastguard Worker }
300*1208bc7eSAndroid Build Coastguard Worker if (RTREE_HEIGHT > 2) {
301*1208bc7eSAndroid Build Coastguard Worker RTREE_GET_CHILD(1)
302*1208bc7eSAndroid Build Coastguard Worker }
303*1208bc7eSAndroid Build Coastguard Worker if (RTREE_HEIGHT > 3) {
304*1208bc7eSAndroid Build Coastguard Worker for (unsigned i = 2; i < RTREE_HEIGHT-1; i++) {
305*1208bc7eSAndroid Build Coastguard Worker RTREE_GET_CHILD(i)
306*1208bc7eSAndroid Build Coastguard Worker }
307*1208bc7eSAndroid Build Coastguard Worker }
308*1208bc7eSAndroid Build Coastguard Worker RTREE_GET_LEAF(RTREE_HEIGHT-1)
309*1208bc7eSAndroid Build Coastguard Worker #undef RTREE_GET_CHILD
310*1208bc7eSAndroid Build Coastguard Worker #undef RTREE_GET_LEAF
311*1208bc7eSAndroid Build Coastguard Worker not_reached();
312*1208bc7eSAndroid Build Coastguard Worker }
313*1208bc7eSAndroid Build Coastguard Worker
314*1208bc7eSAndroid Build Coastguard Worker void
rtree_ctx_data_init(rtree_ctx_t * ctx)315*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_data_init(rtree_ctx_t *ctx) {
316*1208bc7eSAndroid Build Coastguard Worker for (unsigned i = 0; i < RTREE_CTX_NCACHE; i++) {
317*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_cache_elm_t *cache = &ctx->cache[i];
318*1208bc7eSAndroid Build Coastguard Worker cache->leafkey = RTREE_LEAFKEY_INVALID;
319*1208bc7eSAndroid Build Coastguard Worker cache->leaf = NULL;
320*1208bc7eSAndroid Build Coastguard Worker }
321*1208bc7eSAndroid Build Coastguard Worker for (unsigned i = 0; i < RTREE_CTX_NCACHE_L2; i++) {
322*1208bc7eSAndroid Build Coastguard Worker rtree_ctx_cache_elm_t *cache = &ctx->l2_cache[i];
323*1208bc7eSAndroid Build Coastguard Worker cache->leafkey = RTREE_LEAFKEY_INVALID;
324*1208bc7eSAndroid Build Coastguard Worker cache->leaf = NULL;
325*1208bc7eSAndroid Build Coastguard Worker }
326*1208bc7eSAndroid Build Coastguard Worker }
327