xref: /aosp_15_r20/external/jemalloc_new/test/unit/rtree.c (revision 1208bc7e437ced7eb82efac44ba17e3beba411da)
1*1208bc7eSAndroid Build Coastguard Worker #include "test/jemalloc_test.h"
2*1208bc7eSAndroid Build Coastguard Worker 
3*1208bc7eSAndroid Build Coastguard Worker #include "jemalloc/internal/rtree.h"
4*1208bc7eSAndroid Build Coastguard Worker 
5*1208bc7eSAndroid Build Coastguard Worker rtree_node_alloc_t *rtree_node_alloc_orig;
6*1208bc7eSAndroid Build Coastguard Worker rtree_node_dalloc_t *rtree_node_dalloc_orig;
7*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_alloc_t *rtree_leaf_alloc_orig;
8*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_dalloc_t *rtree_leaf_dalloc_orig;
9*1208bc7eSAndroid Build Coastguard Worker 
10*1208bc7eSAndroid Build Coastguard Worker /* Potentially too large to safely place on the stack. */
11*1208bc7eSAndroid Build Coastguard Worker rtree_t test_rtree;
12*1208bc7eSAndroid Build Coastguard Worker 
13*1208bc7eSAndroid Build Coastguard Worker static rtree_node_elm_t *
rtree_node_alloc_intercept(tsdn_t * tsdn,rtree_t * rtree,size_t nelms)14*1208bc7eSAndroid Build Coastguard Worker rtree_node_alloc_intercept(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) {
15*1208bc7eSAndroid Build Coastguard Worker 	rtree_node_elm_t *node;
16*1208bc7eSAndroid Build Coastguard Worker 
17*1208bc7eSAndroid Build Coastguard Worker 	if (rtree != &test_rtree) {
18*1208bc7eSAndroid Build Coastguard Worker 		return rtree_node_alloc_orig(tsdn, rtree, nelms);
19*1208bc7eSAndroid Build Coastguard Worker 	}
20*1208bc7eSAndroid Build Coastguard Worker 
21*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_unlock(tsdn, &rtree->init_lock);
22*1208bc7eSAndroid Build Coastguard Worker 	node = (rtree_node_elm_t *)calloc(nelms, sizeof(rtree_node_elm_t));
23*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_not_null(node, "Unexpected calloc() failure");
24*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_lock(tsdn, &rtree->init_lock);
25*1208bc7eSAndroid Build Coastguard Worker 
26*1208bc7eSAndroid Build Coastguard Worker 	return node;
27*1208bc7eSAndroid Build Coastguard Worker }
28*1208bc7eSAndroid Build Coastguard Worker 
29*1208bc7eSAndroid Build Coastguard Worker static void
rtree_node_dalloc_intercept(tsdn_t * tsdn,rtree_t * rtree,rtree_node_elm_t * node)30*1208bc7eSAndroid Build Coastguard Worker rtree_node_dalloc_intercept(tsdn_t *tsdn, rtree_t *rtree,
31*1208bc7eSAndroid Build Coastguard Worker     rtree_node_elm_t *node) {
32*1208bc7eSAndroid Build Coastguard Worker 	if (rtree != &test_rtree) {
33*1208bc7eSAndroid Build Coastguard Worker 		rtree_node_dalloc_orig(tsdn, rtree, node);
34*1208bc7eSAndroid Build Coastguard Worker 		return;
35*1208bc7eSAndroid Build Coastguard Worker 	}
36*1208bc7eSAndroid Build Coastguard Worker 
37*1208bc7eSAndroid Build Coastguard Worker 	free(node);
38*1208bc7eSAndroid Build Coastguard Worker }
39*1208bc7eSAndroid Build Coastguard Worker 
40*1208bc7eSAndroid Build Coastguard Worker static rtree_leaf_elm_t *
rtree_leaf_alloc_intercept(tsdn_t * tsdn,rtree_t * rtree,size_t nelms)41*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_alloc_intercept(tsdn_t *tsdn, rtree_t *rtree, size_t nelms) {
42*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_elm_t *leaf;
43*1208bc7eSAndroid Build Coastguard Worker 
44*1208bc7eSAndroid Build Coastguard Worker 	if (rtree != &test_rtree) {
45*1208bc7eSAndroid Build Coastguard Worker 		return rtree_leaf_alloc_orig(tsdn, rtree, nelms);
46*1208bc7eSAndroid Build Coastguard Worker 	}
47*1208bc7eSAndroid Build Coastguard Worker 
48*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_unlock(tsdn, &rtree->init_lock);
49*1208bc7eSAndroid Build Coastguard Worker 	leaf = (rtree_leaf_elm_t *)calloc(nelms, sizeof(rtree_leaf_elm_t));
50*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_not_null(leaf, "Unexpected calloc() failure");
51*1208bc7eSAndroid Build Coastguard Worker 	malloc_mutex_lock(tsdn, &rtree->init_lock);
52*1208bc7eSAndroid Build Coastguard Worker 
53*1208bc7eSAndroid Build Coastguard Worker 	return leaf;
54*1208bc7eSAndroid Build Coastguard Worker }
55*1208bc7eSAndroid Build Coastguard Worker 
56*1208bc7eSAndroid Build Coastguard Worker static void
rtree_leaf_dalloc_intercept(tsdn_t * tsdn,rtree_t * rtree,rtree_leaf_elm_t * leaf)57*1208bc7eSAndroid Build Coastguard Worker rtree_leaf_dalloc_intercept(tsdn_t *tsdn, rtree_t *rtree,
58*1208bc7eSAndroid Build Coastguard Worker     rtree_leaf_elm_t *leaf) {
59*1208bc7eSAndroid Build Coastguard Worker 	if (rtree != &test_rtree) {
60*1208bc7eSAndroid Build Coastguard Worker 		rtree_leaf_dalloc_orig(tsdn, rtree, leaf);
61*1208bc7eSAndroid Build Coastguard Worker 		return;
62*1208bc7eSAndroid Build Coastguard Worker 	}
63*1208bc7eSAndroid Build Coastguard Worker 
64*1208bc7eSAndroid Build Coastguard Worker 	free(leaf);
65*1208bc7eSAndroid Build Coastguard Worker }
66*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_rtree_read_empty)67*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_rtree_read_empty) {
68*1208bc7eSAndroid Build Coastguard Worker 	tsdn_t *tsdn;
69*1208bc7eSAndroid Build Coastguard Worker 
70*1208bc7eSAndroid Build Coastguard Worker 	tsdn = tsdn_fetch();
71*1208bc7eSAndroid Build Coastguard Worker 
72*1208bc7eSAndroid Build Coastguard Worker 	rtree_t *rtree = &test_rtree;
73*1208bc7eSAndroid Build Coastguard Worker 	rtree_ctx_t rtree_ctx;
74*1208bc7eSAndroid Build Coastguard Worker 	rtree_ctx_data_init(&rtree_ctx);
75*1208bc7eSAndroid Build Coastguard Worker 	assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
76*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx, PAGE,
77*1208bc7eSAndroid Build Coastguard Worker 	    false), "rtree_extent_read() should return NULL for empty tree");
78*1208bc7eSAndroid Build Coastguard Worker 	rtree_delete(tsdn, rtree);
79*1208bc7eSAndroid Build Coastguard Worker }
80*1208bc7eSAndroid Build Coastguard Worker TEST_END
81*1208bc7eSAndroid Build Coastguard Worker 
82*1208bc7eSAndroid Build Coastguard Worker #undef NTHREADS
83*1208bc7eSAndroid Build Coastguard Worker #undef NITERS
84*1208bc7eSAndroid Build Coastguard Worker #undef SEED
85*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_rtree_extrema)86*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_rtree_extrema) {
87*1208bc7eSAndroid Build Coastguard Worker 	extent_t extent_a, extent_b;
88*1208bc7eSAndroid Build Coastguard Worker 	extent_init(&extent_a, NULL, NULL, LARGE_MINCLASS, false,
89*1208bc7eSAndroid Build Coastguard Worker 	    sz_size2index(LARGE_MINCLASS), 0, extent_state_active, false,
90*1208bc7eSAndroid Build Coastguard Worker 	    false, true);
91*1208bc7eSAndroid Build Coastguard Worker 	extent_init(&extent_b, NULL, NULL, 0, false, NSIZES, 0,
92*1208bc7eSAndroid Build Coastguard Worker 	    extent_state_active, false, false, true);
93*1208bc7eSAndroid Build Coastguard Worker 
94*1208bc7eSAndroid Build Coastguard Worker 	tsdn_t *tsdn = tsdn_fetch();
95*1208bc7eSAndroid Build Coastguard Worker 
96*1208bc7eSAndroid Build Coastguard Worker 	rtree_t *rtree = &test_rtree;
97*1208bc7eSAndroid Build Coastguard Worker 	rtree_ctx_t rtree_ctx;
98*1208bc7eSAndroid Build Coastguard Worker 	rtree_ctx_data_init(&rtree_ctx);
99*1208bc7eSAndroid Build Coastguard Worker 	assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
100*1208bc7eSAndroid Build Coastguard Worker 
101*1208bc7eSAndroid Build Coastguard Worker 	assert_false(rtree_write(tsdn, rtree, &rtree_ctx, PAGE, &extent_a,
102*1208bc7eSAndroid Build Coastguard Worker 	    extent_szind_get(&extent_a), extent_slab_get(&extent_a)),
103*1208bc7eSAndroid Build Coastguard Worker 	    "Unexpected rtree_write() failure");
104*1208bc7eSAndroid Build Coastguard Worker 	rtree_szind_slab_update(tsdn, rtree, &rtree_ctx, PAGE,
105*1208bc7eSAndroid Build Coastguard Worker 	    extent_szind_get(&extent_a), extent_slab_get(&extent_a));
106*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx, PAGE, true),
107*1208bc7eSAndroid Build Coastguard Worker 	    &extent_a,
108*1208bc7eSAndroid Build Coastguard Worker 	    "rtree_extent_read() should return previously set value");
109*1208bc7eSAndroid Build Coastguard Worker 
110*1208bc7eSAndroid Build Coastguard Worker 	assert_false(rtree_write(tsdn, rtree, &rtree_ctx, ~((uintptr_t)0),
111*1208bc7eSAndroid Build Coastguard Worker 	    &extent_b, extent_szind_get_maybe_invalid(&extent_b),
112*1208bc7eSAndroid Build Coastguard Worker 	    extent_slab_get(&extent_b)), "Unexpected rtree_write() failure");
113*1208bc7eSAndroid Build Coastguard Worker 	assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
114*1208bc7eSAndroid Build Coastguard Worker 	    ~((uintptr_t)0), true), &extent_b,
115*1208bc7eSAndroid Build Coastguard Worker 	    "rtree_extent_read() should return previously set value");
116*1208bc7eSAndroid Build Coastguard Worker 
117*1208bc7eSAndroid Build Coastguard Worker 	rtree_delete(tsdn, rtree);
118*1208bc7eSAndroid Build Coastguard Worker }
119*1208bc7eSAndroid Build Coastguard Worker TEST_END
120*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_rtree_bits)121*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_rtree_bits) {
122*1208bc7eSAndroid Build Coastguard Worker 	tsdn_t *tsdn = tsdn_fetch();
123*1208bc7eSAndroid Build Coastguard Worker 
124*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t keys[] = {PAGE, PAGE + 1,
125*1208bc7eSAndroid Build Coastguard Worker 	    PAGE + (((uintptr_t)1) << LG_PAGE) - 1};
126*1208bc7eSAndroid Build Coastguard Worker 
127*1208bc7eSAndroid Build Coastguard Worker 	extent_t extent;
128*1208bc7eSAndroid Build Coastguard Worker 	extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0,
129*1208bc7eSAndroid Build Coastguard Worker 	    extent_state_active, false, false, true);
130*1208bc7eSAndroid Build Coastguard Worker 
131*1208bc7eSAndroid Build Coastguard Worker 	rtree_t *rtree = &test_rtree;
132*1208bc7eSAndroid Build Coastguard Worker 	rtree_ctx_t rtree_ctx;
133*1208bc7eSAndroid Build Coastguard Worker 	rtree_ctx_data_init(&rtree_ctx);
134*1208bc7eSAndroid Build Coastguard Worker 	assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
135*1208bc7eSAndroid Build Coastguard Worker 
136*1208bc7eSAndroid Build Coastguard Worker 	for (unsigned i = 0; i < sizeof(keys)/sizeof(uintptr_t); i++) {
137*1208bc7eSAndroid Build Coastguard Worker 		assert_false(rtree_write(tsdn, rtree, &rtree_ctx, keys[i],
138*1208bc7eSAndroid Build Coastguard Worker 		    &extent, NSIZES, false),
139*1208bc7eSAndroid Build Coastguard Worker 		    "Unexpected rtree_write() failure");
140*1208bc7eSAndroid Build Coastguard Worker 		for (unsigned j = 0; j < sizeof(keys)/sizeof(uintptr_t); j++) {
141*1208bc7eSAndroid Build Coastguard Worker 			assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
142*1208bc7eSAndroid Build Coastguard Worker 			    keys[j], true), &extent,
143*1208bc7eSAndroid Build Coastguard Worker 			    "rtree_extent_read() should return previously set "
144*1208bc7eSAndroid Build Coastguard Worker 			    "value and ignore insignificant key bits; i=%u, "
145*1208bc7eSAndroid Build Coastguard Worker 			    "j=%u, set key=%#"FMTxPTR", get key=%#"FMTxPTR, i,
146*1208bc7eSAndroid Build Coastguard Worker 			    j, keys[i], keys[j]);
147*1208bc7eSAndroid Build Coastguard Worker 		}
148*1208bc7eSAndroid Build Coastguard Worker 		assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
149*1208bc7eSAndroid Build Coastguard Worker 		    (((uintptr_t)2) << LG_PAGE), false),
150*1208bc7eSAndroid Build Coastguard Worker 		    "Only leftmost rtree leaf should be set; i=%u", i);
151*1208bc7eSAndroid Build Coastguard Worker 		rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
152*1208bc7eSAndroid Build Coastguard Worker 	}
153*1208bc7eSAndroid Build Coastguard Worker 
154*1208bc7eSAndroid Build Coastguard Worker 	rtree_delete(tsdn, rtree);
155*1208bc7eSAndroid Build Coastguard Worker }
156*1208bc7eSAndroid Build Coastguard Worker TEST_END
157*1208bc7eSAndroid Build Coastguard Worker 
TEST_BEGIN(test_rtree_random)158*1208bc7eSAndroid Build Coastguard Worker TEST_BEGIN(test_rtree_random) {
159*1208bc7eSAndroid Build Coastguard Worker #define NSET 16
160*1208bc7eSAndroid Build Coastguard Worker #define SEED 42
161*1208bc7eSAndroid Build Coastguard Worker 	sfmt_t *sfmt = init_gen_rand(SEED);
162*1208bc7eSAndroid Build Coastguard Worker 	tsdn_t *tsdn = tsdn_fetch();
163*1208bc7eSAndroid Build Coastguard Worker 	uintptr_t keys[NSET];
164*1208bc7eSAndroid Build Coastguard Worker 	rtree_t *rtree = &test_rtree;
165*1208bc7eSAndroid Build Coastguard Worker 	rtree_ctx_t rtree_ctx;
166*1208bc7eSAndroid Build Coastguard Worker 	rtree_ctx_data_init(&rtree_ctx);
167*1208bc7eSAndroid Build Coastguard Worker 
168*1208bc7eSAndroid Build Coastguard Worker 	extent_t extent;
169*1208bc7eSAndroid Build Coastguard Worker 	extent_init(&extent, NULL, NULL, 0, false, NSIZES, 0,
170*1208bc7eSAndroid Build Coastguard Worker 	    extent_state_active, false, false, true);
171*1208bc7eSAndroid Build Coastguard Worker 
172*1208bc7eSAndroid Build Coastguard Worker 	assert_false(rtree_new(rtree, false), "Unexpected rtree_new() failure");
173*1208bc7eSAndroid Build Coastguard Worker 
174*1208bc7eSAndroid Build Coastguard Worker 	for (unsigned i = 0; i < NSET; i++) {
175*1208bc7eSAndroid Build Coastguard Worker 		keys[i] = (uintptr_t)gen_rand64(sfmt);
176*1208bc7eSAndroid Build Coastguard Worker 		rtree_leaf_elm_t *elm = rtree_leaf_elm_lookup(tsdn, rtree,
177*1208bc7eSAndroid Build Coastguard Worker 		    &rtree_ctx, keys[i], false, true);
178*1208bc7eSAndroid Build Coastguard Worker 		assert_ptr_not_null(elm,
179*1208bc7eSAndroid Build Coastguard Worker 		    "Unexpected rtree_leaf_elm_lookup() failure");
180*1208bc7eSAndroid Build Coastguard Worker 		rtree_leaf_elm_write(tsdn, rtree, elm, &extent, NSIZES, false);
181*1208bc7eSAndroid Build Coastguard Worker 		assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
182*1208bc7eSAndroid Build Coastguard Worker 		    keys[i], true), &extent,
183*1208bc7eSAndroid Build Coastguard Worker 		    "rtree_extent_read() should return previously set value");
184*1208bc7eSAndroid Build Coastguard Worker 	}
185*1208bc7eSAndroid Build Coastguard Worker 	for (unsigned i = 0; i < NSET; i++) {
186*1208bc7eSAndroid Build Coastguard Worker 		assert_ptr_eq(rtree_extent_read(tsdn, rtree, &rtree_ctx,
187*1208bc7eSAndroid Build Coastguard Worker 		    keys[i], true), &extent,
188*1208bc7eSAndroid Build Coastguard Worker 		    "rtree_extent_read() should return previously set value, "
189*1208bc7eSAndroid Build Coastguard Worker 		    "i=%u", i);
190*1208bc7eSAndroid Build Coastguard Worker 	}
191*1208bc7eSAndroid Build Coastguard Worker 
192*1208bc7eSAndroid Build Coastguard Worker 	for (unsigned i = 0; i < NSET; i++) {
193*1208bc7eSAndroid Build Coastguard Worker 		rtree_clear(tsdn, rtree, &rtree_ctx, keys[i]);
194*1208bc7eSAndroid Build Coastguard Worker 		assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
195*1208bc7eSAndroid Build Coastguard Worker 		    keys[i], true),
196*1208bc7eSAndroid Build Coastguard Worker 		   "rtree_extent_read() should return previously set value");
197*1208bc7eSAndroid Build Coastguard Worker 	}
198*1208bc7eSAndroid Build Coastguard Worker 	for (unsigned i = 0; i < NSET; i++) {
199*1208bc7eSAndroid Build Coastguard Worker 		assert_ptr_null(rtree_extent_read(tsdn, rtree, &rtree_ctx,
200*1208bc7eSAndroid Build Coastguard Worker 		    keys[i], true),
201*1208bc7eSAndroid Build Coastguard Worker 		    "rtree_extent_read() should return previously set value");
202*1208bc7eSAndroid Build Coastguard Worker 	}
203*1208bc7eSAndroid Build Coastguard Worker 
204*1208bc7eSAndroid Build Coastguard Worker 	rtree_delete(tsdn, rtree);
205*1208bc7eSAndroid Build Coastguard Worker 	fini_gen_rand(sfmt);
206*1208bc7eSAndroid Build Coastguard Worker #undef NSET
207*1208bc7eSAndroid Build Coastguard Worker #undef SEED
208*1208bc7eSAndroid Build Coastguard Worker }
209*1208bc7eSAndroid Build Coastguard Worker TEST_END
210*1208bc7eSAndroid Build Coastguard Worker 
211*1208bc7eSAndroid Build Coastguard Worker int
main(void)212*1208bc7eSAndroid Build Coastguard Worker main(void) {
213*1208bc7eSAndroid Build Coastguard Worker 	rtree_node_alloc_orig = rtree_node_alloc;
214*1208bc7eSAndroid Build Coastguard Worker 	rtree_node_alloc = rtree_node_alloc_intercept;
215*1208bc7eSAndroid Build Coastguard Worker 	rtree_node_dalloc_orig = rtree_node_dalloc;
216*1208bc7eSAndroid Build Coastguard Worker 	rtree_node_dalloc = rtree_node_dalloc_intercept;
217*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_alloc_orig = rtree_leaf_alloc;
218*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_alloc = rtree_leaf_alloc_intercept;
219*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_dalloc_orig = rtree_leaf_dalloc;
220*1208bc7eSAndroid Build Coastguard Worker 	rtree_leaf_dalloc = rtree_leaf_dalloc_intercept;
221*1208bc7eSAndroid Build Coastguard Worker 
222*1208bc7eSAndroid Build Coastguard Worker 	return test(
223*1208bc7eSAndroid Build Coastguard Worker 	    test_rtree_read_empty,
224*1208bc7eSAndroid Build Coastguard Worker 	    test_rtree_extrema,
225*1208bc7eSAndroid Build Coastguard Worker 	    test_rtree_bits,
226*1208bc7eSAndroid Build Coastguard Worker 	    test_rtree_random);
227*1208bc7eSAndroid Build Coastguard Worker }
228