xref: /openbmc/linux/tools/testing/radix-tree/main.c (revision 1366c37ed84b166a0fffe201154b0d3b78a3976b)
1*1366c37eSMatthew Wilcox #include <stdio.h>
2*1366c37eSMatthew Wilcox #include <stdlib.h>
3*1366c37eSMatthew Wilcox #include <unistd.h>
4*1366c37eSMatthew Wilcox #include <time.h>
5*1366c37eSMatthew Wilcox #include <assert.h>
6*1366c37eSMatthew Wilcox 
7*1366c37eSMatthew Wilcox #include <linux/slab.h>
8*1366c37eSMatthew Wilcox #include <linux/radix-tree.h>
9*1366c37eSMatthew Wilcox 
10*1366c37eSMatthew Wilcox #include "test.h"
11*1366c37eSMatthew Wilcox #include "regression.h"
12*1366c37eSMatthew Wilcox 
13*1366c37eSMatthew Wilcox void __gang_check(unsigned long middle, long down, long up, int chunk, int hop)
14*1366c37eSMatthew Wilcox {
15*1366c37eSMatthew Wilcox 	long idx;
16*1366c37eSMatthew Wilcox 	RADIX_TREE(tree, GFP_KERNEL);
17*1366c37eSMatthew Wilcox 
18*1366c37eSMatthew Wilcox 	middle = 1 << 30;
19*1366c37eSMatthew Wilcox 
20*1366c37eSMatthew Wilcox 	for (idx = -down; idx < up; idx++)
21*1366c37eSMatthew Wilcox 		item_insert(&tree, middle + idx);
22*1366c37eSMatthew Wilcox 
23*1366c37eSMatthew Wilcox 	item_check_absent(&tree, middle - down - 1);
24*1366c37eSMatthew Wilcox 	for (idx = -down; idx < up; idx++)
25*1366c37eSMatthew Wilcox 		item_check_present(&tree, middle + idx);
26*1366c37eSMatthew Wilcox 	item_check_absent(&tree, middle + up);
27*1366c37eSMatthew Wilcox 
28*1366c37eSMatthew Wilcox 	item_gang_check_present(&tree, middle - down,
29*1366c37eSMatthew Wilcox 			up + down, chunk, hop);
30*1366c37eSMatthew Wilcox 	item_full_scan(&tree, middle - down, down + up, chunk);
31*1366c37eSMatthew Wilcox 	item_kill_tree(&tree);
32*1366c37eSMatthew Wilcox }
33*1366c37eSMatthew Wilcox 
34*1366c37eSMatthew Wilcox void gang_check(void)
35*1366c37eSMatthew Wilcox {
36*1366c37eSMatthew Wilcox 	__gang_check(1 << 30, 128, 128, 35, 2);
37*1366c37eSMatthew Wilcox 	__gang_check(1 << 31, 128, 128, 32, 32);
38*1366c37eSMatthew Wilcox 	__gang_check(1 << 31, 128, 128, 32, 100);
39*1366c37eSMatthew Wilcox 	__gang_check(1 << 31, 128, 128, 17, 7);
40*1366c37eSMatthew Wilcox 	__gang_check(0xffff0000, 0, 65536, 17, 7);
41*1366c37eSMatthew Wilcox 	__gang_check(0xfffffffe, 1, 1, 17, 7);
42*1366c37eSMatthew Wilcox }
43*1366c37eSMatthew Wilcox 
44*1366c37eSMatthew Wilcox void __big_gang_check(void)
45*1366c37eSMatthew Wilcox {
46*1366c37eSMatthew Wilcox 	unsigned long start;
47*1366c37eSMatthew Wilcox 	int wrapped = 0;
48*1366c37eSMatthew Wilcox 
49*1366c37eSMatthew Wilcox 	start = 0;
50*1366c37eSMatthew Wilcox 	do {
51*1366c37eSMatthew Wilcox 		unsigned long old_start;
52*1366c37eSMatthew Wilcox 
53*1366c37eSMatthew Wilcox //		printf("0x%08lx\n", start);
54*1366c37eSMatthew Wilcox 		__gang_check(start, rand() % 113 + 1, rand() % 71,
55*1366c37eSMatthew Wilcox 				rand() % 157, rand() % 91 + 1);
56*1366c37eSMatthew Wilcox 		old_start = start;
57*1366c37eSMatthew Wilcox 		start += rand() % 1000000;
58*1366c37eSMatthew Wilcox 		start %= 1ULL << 33;
59*1366c37eSMatthew Wilcox 		if (start < old_start)
60*1366c37eSMatthew Wilcox 			wrapped = 1;
61*1366c37eSMatthew Wilcox 	} while (!wrapped);
62*1366c37eSMatthew Wilcox }
63*1366c37eSMatthew Wilcox 
64*1366c37eSMatthew Wilcox void big_gang_check(void)
65*1366c37eSMatthew Wilcox {
66*1366c37eSMatthew Wilcox 	int i;
67*1366c37eSMatthew Wilcox 
68*1366c37eSMatthew Wilcox 	for (i = 0; i < 1000; i++) {
69*1366c37eSMatthew Wilcox 		__big_gang_check();
70*1366c37eSMatthew Wilcox 		srand(time(0));
71*1366c37eSMatthew Wilcox 		printf("%d ", i);
72*1366c37eSMatthew Wilcox 		fflush(stdout);
73*1366c37eSMatthew Wilcox 	}
74*1366c37eSMatthew Wilcox }
75*1366c37eSMatthew Wilcox 
76*1366c37eSMatthew Wilcox void add_and_check(void)
77*1366c37eSMatthew Wilcox {
78*1366c37eSMatthew Wilcox 	RADIX_TREE(tree, GFP_KERNEL);
79*1366c37eSMatthew Wilcox 
80*1366c37eSMatthew Wilcox 	item_insert(&tree, 44);
81*1366c37eSMatthew Wilcox 	item_check_present(&tree, 44);
82*1366c37eSMatthew Wilcox 	item_check_absent(&tree, 43);
83*1366c37eSMatthew Wilcox 	item_kill_tree(&tree);
84*1366c37eSMatthew Wilcox }
85*1366c37eSMatthew Wilcox 
86*1366c37eSMatthew Wilcox void dynamic_height_check(void)
87*1366c37eSMatthew Wilcox {
88*1366c37eSMatthew Wilcox 	int i;
89*1366c37eSMatthew Wilcox 	RADIX_TREE(tree, GFP_KERNEL);
90*1366c37eSMatthew Wilcox 	tree_verify_min_height(&tree, 0);
91*1366c37eSMatthew Wilcox 
92*1366c37eSMatthew Wilcox 	item_insert(&tree, 42);
93*1366c37eSMatthew Wilcox 	tree_verify_min_height(&tree, 42);
94*1366c37eSMatthew Wilcox 
95*1366c37eSMatthew Wilcox 	item_insert(&tree, 1000000);
96*1366c37eSMatthew Wilcox 	tree_verify_min_height(&tree, 1000000);
97*1366c37eSMatthew Wilcox 
98*1366c37eSMatthew Wilcox 	assert(item_delete(&tree, 1000000));
99*1366c37eSMatthew Wilcox 	tree_verify_min_height(&tree, 42);
100*1366c37eSMatthew Wilcox 
101*1366c37eSMatthew Wilcox 	assert(item_delete(&tree, 42));
102*1366c37eSMatthew Wilcox 	tree_verify_min_height(&tree, 0);
103*1366c37eSMatthew Wilcox 
104*1366c37eSMatthew Wilcox 	for (i = 0; i < 1000; i++) {
105*1366c37eSMatthew Wilcox 		item_insert(&tree, i);
106*1366c37eSMatthew Wilcox 		tree_verify_min_height(&tree, i);
107*1366c37eSMatthew Wilcox 	}
108*1366c37eSMatthew Wilcox 
109*1366c37eSMatthew Wilcox 	i--;
110*1366c37eSMatthew Wilcox 	for (;;) {
111*1366c37eSMatthew Wilcox 		assert(item_delete(&tree, i));
112*1366c37eSMatthew Wilcox 		if (i == 0) {
113*1366c37eSMatthew Wilcox 			tree_verify_min_height(&tree, 0);
114*1366c37eSMatthew Wilcox 			break;
115*1366c37eSMatthew Wilcox 		}
116*1366c37eSMatthew Wilcox 		i--;
117*1366c37eSMatthew Wilcox 		tree_verify_min_height(&tree, i);
118*1366c37eSMatthew Wilcox 	}
119*1366c37eSMatthew Wilcox 
120*1366c37eSMatthew Wilcox 	item_kill_tree(&tree);
121*1366c37eSMatthew Wilcox }
122*1366c37eSMatthew Wilcox 
123*1366c37eSMatthew Wilcox void check_copied_tags(struct radix_tree_root *tree, unsigned long start, unsigned long end, unsigned long *idx, int count, int fromtag, int totag)
124*1366c37eSMatthew Wilcox {
125*1366c37eSMatthew Wilcox 	int i;
126*1366c37eSMatthew Wilcox 
127*1366c37eSMatthew Wilcox 	for (i = 0; i < count; i++) {
128*1366c37eSMatthew Wilcox /*		if (i % 1000 == 0)
129*1366c37eSMatthew Wilcox 			putchar('.'); */
130*1366c37eSMatthew Wilcox 		if (idx[i] < start || idx[i] > end) {
131*1366c37eSMatthew Wilcox 			if (item_tag_get(tree, idx[i], totag)) {
132*1366c37eSMatthew Wilcox 				printf("%lu-%lu: %lu, tags %d-%d\n", start, end, idx[i], item_tag_get(tree, idx[i], fromtag), item_tag_get(tree, idx[i], totag));
133*1366c37eSMatthew Wilcox 			}
134*1366c37eSMatthew Wilcox 			assert(!item_tag_get(tree, idx[i], totag));
135*1366c37eSMatthew Wilcox 			continue;
136*1366c37eSMatthew Wilcox 		}
137*1366c37eSMatthew Wilcox 		if (item_tag_get(tree, idx[i], fromtag) ^
138*1366c37eSMatthew Wilcox 			item_tag_get(tree, idx[i], totag)) {
139*1366c37eSMatthew Wilcox 			printf("%lu-%lu: %lu, tags %d-%d\n", start, end, idx[i], item_tag_get(tree, idx[i], fromtag), item_tag_get(tree, idx[i], totag));
140*1366c37eSMatthew Wilcox 		}
141*1366c37eSMatthew Wilcox 		assert(!(item_tag_get(tree, idx[i], fromtag) ^
142*1366c37eSMatthew Wilcox 			 item_tag_get(tree, idx[i], totag)));
143*1366c37eSMatthew Wilcox 	}
144*1366c37eSMatthew Wilcox }
145*1366c37eSMatthew Wilcox 
146*1366c37eSMatthew Wilcox #define ITEMS 50000
147*1366c37eSMatthew Wilcox 
148*1366c37eSMatthew Wilcox void copy_tag_check(void)
149*1366c37eSMatthew Wilcox {
150*1366c37eSMatthew Wilcox 	RADIX_TREE(tree, GFP_KERNEL);
151*1366c37eSMatthew Wilcox 	unsigned long idx[ITEMS];
152*1366c37eSMatthew Wilcox 	unsigned long start, end, count = 0, tagged, cur, tmp;
153*1366c37eSMatthew Wilcox 	int i;
154*1366c37eSMatthew Wilcox 
155*1366c37eSMatthew Wilcox //	printf("generating radix tree indices...\n");
156*1366c37eSMatthew Wilcox 	start = rand();
157*1366c37eSMatthew Wilcox 	end = rand();
158*1366c37eSMatthew Wilcox 	if (start > end && (rand() % 10)) {
159*1366c37eSMatthew Wilcox 		cur = start;
160*1366c37eSMatthew Wilcox 		start = end;
161*1366c37eSMatthew Wilcox 		end = cur;
162*1366c37eSMatthew Wilcox 	}
163*1366c37eSMatthew Wilcox 	/* Specifically create items around the start and the end of the range
164*1366c37eSMatthew Wilcox 	 * with high probability to check for off by one errors */
165*1366c37eSMatthew Wilcox 	cur = rand();
166*1366c37eSMatthew Wilcox 	if (cur & 1) {
167*1366c37eSMatthew Wilcox 		item_insert(&tree, start);
168*1366c37eSMatthew Wilcox 		if (cur & 2) {
169*1366c37eSMatthew Wilcox 			if (start <= end)
170*1366c37eSMatthew Wilcox 				count++;
171*1366c37eSMatthew Wilcox 			item_tag_set(&tree, start, 0);
172*1366c37eSMatthew Wilcox 		}
173*1366c37eSMatthew Wilcox 	}
174*1366c37eSMatthew Wilcox 	if (cur & 4) {
175*1366c37eSMatthew Wilcox 		item_insert(&tree, start-1);
176*1366c37eSMatthew Wilcox 		if (cur & 8)
177*1366c37eSMatthew Wilcox 			item_tag_set(&tree, start-1, 0);
178*1366c37eSMatthew Wilcox 	}
179*1366c37eSMatthew Wilcox 	if (cur & 16) {
180*1366c37eSMatthew Wilcox 		item_insert(&tree, end);
181*1366c37eSMatthew Wilcox 		if (cur & 32) {
182*1366c37eSMatthew Wilcox 			if (start <= end)
183*1366c37eSMatthew Wilcox 				count++;
184*1366c37eSMatthew Wilcox 			item_tag_set(&tree, end, 0);
185*1366c37eSMatthew Wilcox 		}
186*1366c37eSMatthew Wilcox 	}
187*1366c37eSMatthew Wilcox 	if (cur & 64) {
188*1366c37eSMatthew Wilcox 		item_insert(&tree, end+1);
189*1366c37eSMatthew Wilcox 		if (cur & 128)
190*1366c37eSMatthew Wilcox 			item_tag_set(&tree, end+1, 0);
191*1366c37eSMatthew Wilcox 	}
192*1366c37eSMatthew Wilcox 
193*1366c37eSMatthew Wilcox 	for (i = 0; i < ITEMS; i++) {
194*1366c37eSMatthew Wilcox 		do {
195*1366c37eSMatthew Wilcox 			idx[i] = rand();
196*1366c37eSMatthew Wilcox 		} while (item_lookup(&tree, idx[i]));
197*1366c37eSMatthew Wilcox 
198*1366c37eSMatthew Wilcox 		item_insert(&tree, idx[i]);
199*1366c37eSMatthew Wilcox 		if (rand() & 1) {
200*1366c37eSMatthew Wilcox 			item_tag_set(&tree, idx[i], 0);
201*1366c37eSMatthew Wilcox 			if (idx[i] >= start && idx[i] <= end)
202*1366c37eSMatthew Wilcox 				count++;
203*1366c37eSMatthew Wilcox 		}
204*1366c37eSMatthew Wilcox /*		if (i % 1000 == 0)
205*1366c37eSMatthew Wilcox 			putchar('.'); */
206*1366c37eSMatthew Wilcox 	}
207*1366c37eSMatthew Wilcox 
208*1366c37eSMatthew Wilcox //	printf("\ncopying tags...\n");
209*1366c37eSMatthew Wilcox 	cur = start;
210*1366c37eSMatthew Wilcox 	tagged = radix_tree_range_tag_if_tagged(&tree, &cur, end, ITEMS, 0, 1);
211*1366c37eSMatthew Wilcox 
212*1366c37eSMatthew Wilcox //	printf("checking copied tags\n");
213*1366c37eSMatthew Wilcox 	assert(tagged == count);
214*1366c37eSMatthew Wilcox 	check_copied_tags(&tree, start, end, idx, ITEMS, 0, 1);
215*1366c37eSMatthew Wilcox 
216*1366c37eSMatthew Wilcox 	/* Copy tags in several rounds */
217*1366c37eSMatthew Wilcox //	printf("\ncopying tags...\n");
218*1366c37eSMatthew Wilcox 	cur = start;
219*1366c37eSMatthew Wilcox 	do {
220*1366c37eSMatthew Wilcox 		tmp = rand() % (count/10+2);
221*1366c37eSMatthew Wilcox 		tagged = radix_tree_range_tag_if_tagged(&tree, &cur, end, tmp, 0, 2);
222*1366c37eSMatthew Wilcox 	} while (tmp == tagged);
223*1366c37eSMatthew Wilcox 
224*1366c37eSMatthew Wilcox //	printf("%lu %lu %lu\n", tagged, tmp, count);
225*1366c37eSMatthew Wilcox //	printf("checking copied tags\n");
226*1366c37eSMatthew Wilcox 	check_copied_tags(&tree, start, end, idx, ITEMS, 0, 2);
227*1366c37eSMatthew Wilcox 	assert(tagged < tmp);
228*1366c37eSMatthew Wilcox 	verify_tag_consistency(&tree, 0);
229*1366c37eSMatthew Wilcox 	verify_tag_consistency(&tree, 1);
230*1366c37eSMatthew Wilcox 	verify_tag_consistency(&tree, 2);
231*1366c37eSMatthew Wilcox //	printf("\n");
232*1366c37eSMatthew Wilcox 	item_kill_tree(&tree);
233*1366c37eSMatthew Wilcox }
234*1366c37eSMatthew Wilcox 
235*1366c37eSMatthew Wilcox static void single_thread_tests(void)
236*1366c37eSMatthew Wilcox {
237*1366c37eSMatthew Wilcox 	int i;
238*1366c37eSMatthew Wilcox 
239*1366c37eSMatthew Wilcox 	tag_check();
240*1366c37eSMatthew Wilcox 	printf("after tag_check: %d allocated\n", nr_allocated);
241*1366c37eSMatthew Wilcox 	gang_check();
242*1366c37eSMatthew Wilcox 	printf("after gang_check: %d allocated\n", nr_allocated);
243*1366c37eSMatthew Wilcox 	add_and_check();
244*1366c37eSMatthew Wilcox 	printf("after add_and_check: %d allocated\n", nr_allocated);
245*1366c37eSMatthew Wilcox 	dynamic_height_check();
246*1366c37eSMatthew Wilcox 	printf("after dynamic_height_check: %d allocated\n", nr_allocated);
247*1366c37eSMatthew Wilcox 	big_gang_check();
248*1366c37eSMatthew Wilcox 	printf("after big_gang_check: %d allocated\n", nr_allocated);
249*1366c37eSMatthew Wilcox 	for (i = 0; i < 2000; i++) {
250*1366c37eSMatthew Wilcox 		copy_tag_check();
251*1366c37eSMatthew Wilcox 		printf("%d ", i);
252*1366c37eSMatthew Wilcox 		fflush(stdout);
253*1366c37eSMatthew Wilcox 	}
254*1366c37eSMatthew Wilcox 	printf("after copy_tag_check: %d allocated\n", nr_allocated);
255*1366c37eSMatthew Wilcox }
256*1366c37eSMatthew Wilcox 
257*1366c37eSMatthew Wilcox int main(void)
258*1366c37eSMatthew Wilcox {
259*1366c37eSMatthew Wilcox 	rcu_register_thread();
260*1366c37eSMatthew Wilcox 	radix_tree_init();
261*1366c37eSMatthew Wilcox 
262*1366c37eSMatthew Wilcox 	regression1_test();
263*1366c37eSMatthew Wilcox 	regression2_test();
264*1366c37eSMatthew Wilcox 	single_thread_tests();
265*1366c37eSMatthew Wilcox 
266*1366c37eSMatthew Wilcox 	sleep(1);
267*1366c37eSMatthew Wilcox 	printf("after sleep(1): %d allocated\n", nr_allocated);
268*1366c37eSMatthew Wilcox 	rcu_unregister_thread();
269*1366c37eSMatthew Wilcox 
270*1366c37eSMatthew Wilcox 	exit(0);
271*1366c37eSMatthew Wilcox }
272