xref: /linux/lib/rbtree_test.c (revision 315cc066)
109c434b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2910a742dSMichel Lespinasse #include <linux/module.h>
3223f8911SDavidlohr Bueso #include <linux/moduleparam.h>
49c079addSMichel Lespinasse #include <linux/rbtree_augmented.h>
5910a742dSMichel Lespinasse #include <linux/random.h>
6223f8911SDavidlohr Bueso #include <linux/slab.h>
7910a742dSMichel Lespinasse #include <asm/timex.h>
8910a742dSMichel Lespinasse 
9223f8911SDavidlohr Bueso #define __param(type, name, init, msg)		\
10223f8911SDavidlohr Bueso 	static type name = init;		\
11223f8911SDavidlohr Bueso 	module_param(name, type, 0444);		\
12223f8911SDavidlohr Bueso 	MODULE_PARM_DESC(name, msg);
13223f8911SDavidlohr Bueso 
14223f8911SDavidlohr Bueso __param(int, nnodes, 100, "Number of nodes in the rb-tree");
150b548e33SDavidlohr Bueso __param(int, perf_loops, 1000, "Number of iterations modifying the rb-tree");
16223f8911SDavidlohr Bueso __param(int, check_loops, 100, "Number of iterations modifying and verifying the rb-tree");
17910a742dSMichel Lespinasse 
18910a742dSMichel Lespinasse struct test_node {
19910a742dSMichel Lespinasse 	u32 key;
20dbf128cbSCody P Schafer 	struct rb_node rb;
21dadf9353SMichel Lespinasse 
22dadf9353SMichel Lespinasse 	/* following fields used for testing augmented rbtree functionality */
23dadf9353SMichel Lespinasse 	u32 val;
24dadf9353SMichel Lespinasse 	u32 augmented;
25910a742dSMichel Lespinasse };
26910a742dSMichel Lespinasse 
27b10d43f9SDavidlohr Bueso static struct rb_root_cached root = RB_ROOT_CACHED;
28223f8911SDavidlohr Bueso static struct test_node *nodes = NULL;
29910a742dSMichel Lespinasse 
30910a742dSMichel Lespinasse static struct rnd_state rnd;
31910a742dSMichel Lespinasse 
insert(struct test_node * node,struct rb_root_cached * root)32b10d43f9SDavidlohr Bueso static void insert(struct test_node *node, struct rb_root_cached *root)
33910a742dSMichel Lespinasse {
34b10d43f9SDavidlohr Bueso 	struct rb_node **new = &root->rb_root.rb_node, *parent = NULL;
35dadf9353SMichel Lespinasse 	u32 key = node->key;
36910a742dSMichel Lespinasse 
37910a742dSMichel Lespinasse 	while (*new) {
38910a742dSMichel Lespinasse 		parent = *new;
39dadf9353SMichel Lespinasse 		if (key < rb_entry(parent, struct test_node, rb)->key)
40910a742dSMichel Lespinasse 			new = &parent->rb_left;
41910a742dSMichel Lespinasse 		else
42910a742dSMichel Lespinasse 			new = &parent->rb_right;
43910a742dSMichel Lespinasse 	}
44910a742dSMichel Lespinasse 
45910a742dSMichel Lespinasse 	rb_link_node(&node->rb, parent, new);
46b10d43f9SDavidlohr Bueso 	rb_insert_color(&node->rb, &root->rb_root);
47910a742dSMichel Lespinasse }
48910a742dSMichel Lespinasse 
insert_cached(struct test_node * node,struct rb_root_cached * root)49b10d43f9SDavidlohr Bueso static void insert_cached(struct test_node *node, struct rb_root_cached *root)
50910a742dSMichel Lespinasse {
51b10d43f9SDavidlohr Bueso 	struct rb_node **new = &root->rb_root.rb_node, *parent = NULL;
52b10d43f9SDavidlohr Bueso 	u32 key = node->key;
53b10d43f9SDavidlohr Bueso 	bool leftmost = true;
54b10d43f9SDavidlohr Bueso 
55b10d43f9SDavidlohr Bueso 	while (*new) {
56b10d43f9SDavidlohr Bueso 		parent = *new;
57b10d43f9SDavidlohr Bueso 		if (key < rb_entry(parent, struct test_node, rb)->key)
58b10d43f9SDavidlohr Bueso 			new = &parent->rb_left;
59b10d43f9SDavidlohr Bueso 		else {
60b10d43f9SDavidlohr Bueso 			new = &parent->rb_right;
61b10d43f9SDavidlohr Bueso 			leftmost = false;
62910a742dSMichel Lespinasse 		}
63b10d43f9SDavidlohr Bueso 	}
64b10d43f9SDavidlohr Bueso 
65b10d43f9SDavidlohr Bueso 	rb_link_node(&node->rb, parent, new);
66b10d43f9SDavidlohr Bueso 	rb_insert_color_cached(&node->rb, root, leftmost);
67b10d43f9SDavidlohr Bueso }
68b10d43f9SDavidlohr Bueso 
erase(struct test_node * node,struct rb_root_cached * root)69b10d43f9SDavidlohr Bueso static inline void erase(struct test_node *node, struct rb_root_cached *root)
70b10d43f9SDavidlohr Bueso {
71b10d43f9SDavidlohr Bueso 	rb_erase(&node->rb, &root->rb_root);
72b10d43f9SDavidlohr Bueso }
73b10d43f9SDavidlohr Bueso 
erase_cached(struct test_node * node,struct rb_root_cached * root)74b10d43f9SDavidlohr Bueso static inline void erase_cached(struct test_node *node, struct rb_root_cached *root)
75b10d43f9SDavidlohr Bueso {
76b10d43f9SDavidlohr Bueso 	rb_erase_cached(&node->rb, root);
77b10d43f9SDavidlohr Bueso }
78b10d43f9SDavidlohr Bueso 
79910a742dSMichel Lespinasse 
80*315cc066SMichel Lespinasse #define NODE_VAL(node) ((node)->val)
81dadf9353SMichel Lespinasse 
RB_DECLARE_CALLBACKS_MAX(static,augment_callbacks,struct test_node,rb,u32,augmented,NODE_VAL)82*315cc066SMichel Lespinasse RB_DECLARE_CALLBACKS_MAX(static, augment_callbacks,
83*315cc066SMichel Lespinasse 			 struct test_node, rb, u32, augmented, NODE_VAL)
84dadf9353SMichel Lespinasse 
85b10d43f9SDavidlohr Bueso static void insert_augmented(struct test_node *node,
86b10d43f9SDavidlohr Bueso 			     struct rb_root_cached *root)
87dadf9353SMichel Lespinasse {
88b10d43f9SDavidlohr Bueso 	struct rb_node **new = &root->rb_root.rb_node, *rb_parent = NULL;
89dadf9353SMichel Lespinasse 	u32 key = node->key;
9014b94af0SMichel Lespinasse 	u32 val = node->val;
9114b94af0SMichel Lespinasse 	struct test_node *parent;
92dadf9353SMichel Lespinasse 
93dadf9353SMichel Lespinasse 	while (*new) {
9414b94af0SMichel Lespinasse 		rb_parent = *new;
9514b94af0SMichel Lespinasse 		parent = rb_entry(rb_parent, struct test_node, rb);
9614b94af0SMichel Lespinasse 		if (parent->augmented < val)
9714b94af0SMichel Lespinasse 			parent->augmented = val;
9814b94af0SMichel Lespinasse 		if (key < parent->key)
9914b94af0SMichel Lespinasse 			new = &parent->rb.rb_left;
100dadf9353SMichel Lespinasse 		else
10114b94af0SMichel Lespinasse 			new = &parent->rb.rb_right;
102dadf9353SMichel Lespinasse 	}
103dadf9353SMichel Lespinasse 
10414b94af0SMichel Lespinasse 	node->augmented = val;
10514b94af0SMichel Lespinasse 	rb_link_node(&node->rb, rb_parent, new);
106b10d43f9SDavidlohr Bueso 	rb_insert_augmented(&node->rb, &root->rb_root, &augment_callbacks);
107dadf9353SMichel Lespinasse }
108dadf9353SMichel Lespinasse 
insert_augmented_cached(struct test_node * node,struct rb_root_cached * root)109b10d43f9SDavidlohr Bueso static void insert_augmented_cached(struct test_node *node,
110b10d43f9SDavidlohr Bueso 				    struct rb_root_cached *root)
111dadf9353SMichel Lespinasse {
112b10d43f9SDavidlohr Bueso 	struct rb_node **new = &root->rb_root.rb_node, *rb_parent = NULL;
113b10d43f9SDavidlohr Bueso 	u32 key = node->key;
114b10d43f9SDavidlohr Bueso 	u32 val = node->val;
115b10d43f9SDavidlohr Bueso 	struct test_node *parent;
116b10d43f9SDavidlohr Bueso 	bool leftmost = true;
117b10d43f9SDavidlohr Bueso 
118b10d43f9SDavidlohr Bueso 	while (*new) {
119b10d43f9SDavidlohr Bueso 		rb_parent = *new;
120b10d43f9SDavidlohr Bueso 		parent = rb_entry(rb_parent, struct test_node, rb);
121b10d43f9SDavidlohr Bueso 		if (parent->augmented < val)
122b10d43f9SDavidlohr Bueso 			parent->augmented = val;
123b10d43f9SDavidlohr Bueso 		if (key < parent->key)
124b10d43f9SDavidlohr Bueso 			new = &parent->rb.rb_left;
125b10d43f9SDavidlohr Bueso 		else {
126b10d43f9SDavidlohr Bueso 			new = &parent->rb.rb_right;
127b10d43f9SDavidlohr Bueso 			leftmost = false;
128b10d43f9SDavidlohr Bueso 		}
129b10d43f9SDavidlohr Bueso 	}
130b10d43f9SDavidlohr Bueso 
131b10d43f9SDavidlohr Bueso 	node->augmented = val;
132b10d43f9SDavidlohr Bueso 	rb_link_node(&node->rb, rb_parent, new);
133b10d43f9SDavidlohr Bueso 	rb_insert_augmented_cached(&node->rb, root,
134b10d43f9SDavidlohr Bueso 				   leftmost, &augment_callbacks);
135b10d43f9SDavidlohr Bueso }
136b10d43f9SDavidlohr Bueso 
137b10d43f9SDavidlohr Bueso 
erase_augmented(struct test_node * node,struct rb_root_cached * root)138b10d43f9SDavidlohr Bueso static void erase_augmented(struct test_node *node, struct rb_root_cached *root)
139b10d43f9SDavidlohr Bueso {
140b10d43f9SDavidlohr Bueso 	rb_erase_augmented(&node->rb, &root->rb_root, &augment_callbacks);
141b10d43f9SDavidlohr Bueso }
142b10d43f9SDavidlohr Bueso 
erase_augmented_cached(struct test_node * node,struct rb_root_cached * root)143b10d43f9SDavidlohr Bueso static void erase_augmented_cached(struct test_node *node,
144b10d43f9SDavidlohr Bueso 				   struct rb_root_cached *root)
145b10d43f9SDavidlohr Bueso {
146b10d43f9SDavidlohr Bueso 	rb_erase_augmented_cached(&node->rb, root, &augment_callbacks);
147dadf9353SMichel Lespinasse }
148dadf9353SMichel Lespinasse 
init(void)149910a742dSMichel Lespinasse static void init(void)
150910a742dSMichel Lespinasse {
151910a742dSMichel Lespinasse 	int i;
152223f8911SDavidlohr Bueso 	for (i = 0; i < nnodes; i++) {
153496f2f93SAkinobu Mita 		nodes[i].key = prandom_u32_state(&rnd);
154496f2f93SAkinobu Mita 		nodes[i].val = prandom_u32_state(&rnd);
155dadf9353SMichel Lespinasse 	}
156910a742dSMichel Lespinasse }
157910a742dSMichel Lespinasse 
is_red(struct rb_node * rb)158910a742dSMichel Lespinasse static bool is_red(struct rb_node *rb)
159910a742dSMichel Lespinasse {
160910a742dSMichel Lespinasse 	return !(rb->__rb_parent_color & 1);
161910a742dSMichel Lespinasse }
162910a742dSMichel Lespinasse 
black_path_count(struct rb_node * rb)163910a742dSMichel Lespinasse static int black_path_count(struct rb_node *rb)
164910a742dSMichel Lespinasse {
165910a742dSMichel Lespinasse 	int count;
166910a742dSMichel Lespinasse 	for (count = 0; rb; rb = rb_parent(rb))
167910a742dSMichel Lespinasse 		count += !is_red(rb);
168910a742dSMichel Lespinasse 	return count;
169910a742dSMichel Lespinasse }
170910a742dSMichel Lespinasse 
check_postorder_foreach(int nr_nodes)171964fe94dSCody P Schafer static void check_postorder_foreach(int nr_nodes)
172964fe94dSCody P Schafer {
173964fe94dSCody P Schafer 	struct test_node *cur, *n;
174964fe94dSCody P Schafer 	int count = 0;
175b10d43f9SDavidlohr Bueso 	rbtree_postorder_for_each_entry_safe(cur, n, &root.rb_root, rb)
176964fe94dSCody P Schafer 		count++;
177964fe94dSCody P Schafer 
178964fe94dSCody P Schafer 	WARN_ON_ONCE(count != nr_nodes);
179964fe94dSCody P Schafer }
180964fe94dSCody P Schafer 
check_postorder(int nr_nodes)181a791a62fSCody P Schafer static void check_postorder(int nr_nodes)
182a791a62fSCody P Schafer {
183a791a62fSCody P Schafer 	struct rb_node *rb;
184a791a62fSCody P Schafer 	int count = 0;
185b10d43f9SDavidlohr Bueso 	for (rb = rb_first_postorder(&root.rb_root); rb; rb = rb_next_postorder(rb))
186a791a62fSCody P Schafer 		count++;
187a791a62fSCody P Schafer 
188a791a62fSCody P Schafer 	WARN_ON_ONCE(count != nr_nodes);
189a791a62fSCody P Schafer }
190a791a62fSCody P Schafer 
check(int nr_nodes)191910a742dSMichel Lespinasse static void check(int nr_nodes)
192910a742dSMichel Lespinasse {
193910a742dSMichel Lespinasse 	struct rb_node *rb;
1944130f0efSDavidlohr Bueso 	int count = 0, blacks = 0;
195910a742dSMichel Lespinasse 	u32 prev_key = 0;
196910a742dSMichel Lespinasse 
197b10d43f9SDavidlohr Bueso 	for (rb = rb_first(&root.rb_root); rb; rb = rb_next(rb)) {
198910a742dSMichel Lespinasse 		struct test_node *node = rb_entry(rb, struct test_node, rb);
199910a742dSMichel Lespinasse 		WARN_ON_ONCE(node->key < prev_key);
200910a742dSMichel Lespinasse 		WARN_ON_ONCE(is_red(rb) &&
201910a742dSMichel Lespinasse 			     (!rb_parent(rb) || is_red(rb_parent(rb))));
202910a742dSMichel Lespinasse 		if (!count)
203910a742dSMichel Lespinasse 			blacks = black_path_count(rb);
204910a742dSMichel Lespinasse 		else
205910a742dSMichel Lespinasse 			WARN_ON_ONCE((!rb->rb_left || !rb->rb_right) &&
206910a742dSMichel Lespinasse 				     blacks != black_path_count(rb));
207910a742dSMichel Lespinasse 		prev_key = node->key;
208910a742dSMichel Lespinasse 		count++;
209910a742dSMichel Lespinasse 	}
2104130f0efSDavidlohr Bueso 
211910a742dSMichel Lespinasse 	WARN_ON_ONCE(count != nr_nodes);
212b10d43f9SDavidlohr Bueso 	WARN_ON_ONCE(count < (1 << black_path_count(rb_last(&root.rb_root))) - 1);
213a791a62fSCody P Schafer 
214a791a62fSCody P Schafer 	check_postorder(nr_nodes);
215964fe94dSCody P Schafer 	check_postorder_foreach(nr_nodes);
216910a742dSMichel Lespinasse }
217910a742dSMichel Lespinasse 
check_augmented(int nr_nodes)218dadf9353SMichel Lespinasse static void check_augmented(int nr_nodes)
219dadf9353SMichel Lespinasse {
220dadf9353SMichel Lespinasse 	struct rb_node *rb;
221dadf9353SMichel Lespinasse 
222dadf9353SMichel Lespinasse 	check(nr_nodes);
223b10d43f9SDavidlohr Bueso 	for (rb = rb_first(&root.rb_root); rb; rb = rb_next(rb)) {
224dadf9353SMichel Lespinasse 		struct test_node *node = rb_entry(rb, struct test_node, rb);
225*315cc066SMichel Lespinasse 		u32 subtree, max = node->val;
226*315cc066SMichel Lespinasse 		if (node->rb.rb_left) {
227*315cc066SMichel Lespinasse 			subtree = rb_entry(node->rb.rb_left, struct test_node,
228*315cc066SMichel Lespinasse 					   rb)->augmented;
229*315cc066SMichel Lespinasse 			if (max < subtree)
230*315cc066SMichel Lespinasse 				max = subtree;
231*315cc066SMichel Lespinasse 		}
232*315cc066SMichel Lespinasse 		if (node->rb.rb_right) {
233*315cc066SMichel Lespinasse 			subtree = rb_entry(node->rb.rb_right, struct test_node,
234*315cc066SMichel Lespinasse 					   rb)->augmented;
235*315cc066SMichel Lespinasse 			if (max < subtree)
236*315cc066SMichel Lespinasse 				max = subtree;
237*315cc066SMichel Lespinasse 		}
238*315cc066SMichel Lespinasse 		WARN_ON_ONCE(node->augmented != max);
239dadf9353SMichel Lespinasse 	}
240dadf9353SMichel Lespinasse }
241dadf9353SMichel Lespinasse 
rbtree_test_init(void)242c75aaa8eSDavidlohr Bueso static int __init rbtree_test_init(void)
243910a742dSMichel Lespinasse {
244910a742dSMichel Lespinasse 	int i, j;
245910a742dSMichel Lespinasse 	cycles_t time1, time2, time;
246977bd8d5SDavidlohr Bueso 	struct rb_node *node;
247910a742dSMichel Lespinasse 
2486da2ec56SKees Cook 	nodes = kmalloc_array(nnodes, sizeof(*nodes), GFP_KERNEL);
249223f8911SDavidlohr Bueso 	if (!nodes)
250223f8911SDavidlohr Bueso 		return -ENOMEM;
251223f8911SDavidlohr Bueso 
252910a742dSMichel Lespinasse 	printk(KERN_ALERT "rbtree testing");
253910a742dSMichel Lespinasse 
254496f2f93SAkinobu Mita 	prandom_seed_state(&rnd, 3141592653589793238ULL);
255910a742dSMichel Lespinasse 	init();
256910a742dSMichel Lespinasse 
257910a742dSMichel Lespinasse 	time1 = get_cycles();
258910a742dSMichel Lespinasse 
259223f8911SDavidlohr Bueso 	for (i = 0; i < perf_loops; i++) {
260223f8911SDavidlohr Bueso 		for (j = 0; j < nnodes; j++)
261910a742dSMichel Lespinasse 			insert(nodes + j, &root);
262223f8911SDavidlohr Bueso 		for (j = 0; j < nnodes; j++)
263910a742dSMichel Lespinasse 			erase(nodes + j, &root);
264910a742dSMichel Lespinasse 	}
265910a742dSMichel Lespinasse 
266910a742dSMichel Lespinasse 	time2 = get_cycles();
267910a742dSMichel Lespinasse 	time = time2 - time1;
268910a742dSMichel Lespinasse 
269223f8911SDavidlohr Bueso 	time = div_u64(time, perf_loops);
270b10d43f9SDavidlohr Bueso 	printk(" -> test 1 (latency of nnodes insert+delete): %llu cycles\n",
271b10d43f9SDavidlohr Bueso 	       (unsigned long long)time);
272b10d43f9SDavidlohr Bueso 
273b10d43f9SDavidlohr Bueso 	time1 = get_cycles();
274b10d43f9SDavidlohr Bueso 
275b10d43f9SDavidlohr Bueso 	for (i = 0; i < perf_loops; i++) {
276b10d43f9SDavidlohr Bueso 		for (j = 0; j < nnodes; j++)
277b10d43f9SDavidlohr Bueso 			insert_cached(nodes + j, &root);
278b10d43f9SDavidlohr Bueso 		for (j = 0; j < nnodes; j++)
279b10d43f9SDavidlohr Bueso 			erase_cached(nodes + j, &root);
280b10d43f9SDavidlohr Bueso 	}
281b10d43f9SDavidlohr Bueso 
282b10d43f9SDavidlohr Bueso 	time2 = get_cycles();
283b10d43f9SDavidlohr Bueso 	time = time2 - time1;
284b10d43f9SDavidlohr Bueso 
285b10d43f9SDavidlohr Bueso 	time = div_u64(time, perf_loops);
286b10d43f9SDavidlohr Bueso 	printk(" -> test 2 (latency of nnodes cached insert+delete): %llu cycles\n",
287b10d43f9SDavidlohr Bueso 	       (unsigned long long)time);
288910a742dSMichel Lespinasse 
289977bd8d5SDavidlohr Bueso 	for (i = 0; i < nnodes; i++)
290977bd8d5SDavidlohr Bueso 		insert(nodes + i, &root);
291977bd8d5SDavidlohr Bueso 
292977bd8d5SDavidlohr Bueso 	time1 = get_cycles();
293977bd8d5SDavidlohr Bueso 
294977bd8d5SDavidlohr Bueso 	for (i = 0; i < perf_loops; i++) {
295b10d43f9SDavidlohr Bueso 		for (node = rb_first(&root.rb_root); node; node = rb_next(node))
296977bd8d5SDavidlohr Bueso 			;
297977bd8d5SDavidlohr Bueso 	}
298977bd8d5SDavidlohr Bueso 
299977bd8d5SDavidlohr Bueso 	time2 = get_cycles();
300977bd8d5SDavidlohr Bueso 	time = time2 - time1;
301977bd8d5SDavidlohr Bueso 
302977bd8d5SDavidlohr Bueso 	time = div_u64(time, perf_loops);
303b10d43f9SDavidlohr Bueso 	printk(" -> test 3 (latency of inorder traversal): %llu cycles\n",
304b10d43f9SDavidlohr Bueso 	       (unsigned long long)time);
305b10d43f9SDavidlohr Bueso 
306b10d43f9SDavidlohr Bueso 	time1 = get_cycles();
307b10d43f9SDavidlohr Bueso 
308b10d43f9SDavidlohr Bueso 	for (i = 0; i < perf_loops; i++)
309b10d43f9SDavidlohr Bueso 		node = rb_first(&root.rb_root);
310b10d43f9SDavidlohr Bueso 
311b10d43f9SDavidlohr Bueso 	time2 = get_cycles();
312b10d43f9SDavidlohr Bueso 	time = time2 - time1;
313b10d43f9SDavidlohr Bueso 
314b10d43f9SDavidlohr Bueso 	time = div_u64(time, perf_loops);
315b10d43f9SDavidlohr Bueso 	printk(" -> test 4 (latency to fetch first node)\n");
316b10d43f9SDavidlohr Bueso 	printk("        non-cached: %llu cycles\n", (unsigned long long)time);
317b10d43f9SDavidlohr Bueso 
318b10d43f9SDavidlohr Bueso 	time1 = get_cycles();
319b10d43f9SDavidlohr Bueso 
320b10d43f9SDavidlohr Bueso 	for (i = 0; i < perf_loops; i++)
321b10d43f9SDavidlohr Bueso 		node = rb_first_cached(&root);
322b10d43f9SDavidlohr Bueso 
323b10d43f9SDavidlohr Bueso 	time2 = get_cycles();
324b10d43f9SDavidlohr Bueso 	time = time2 - time1;
325b10d43f9SDavidlohr Bueso 
326b10d43f9SDavidlohr Bueso 	time = div_u64(time, perf_loops);
327b10d43f9SDavidlohr Bueso 	printk("        cached: %llu cycles\n", (unsigned long long)time);
328977bd8d5SDavidlohr Bueso 
329977bd8d5SDavidlohr Bueso 	for (i = 0; i < nnodes; i++)
330977bd8d5SDavidlohr Bueso 		erase(nodes + i, &root);
331977bd8d5SDavidlohr Bueso 
332977bd8d5SDavidlohr Bueso 	/* run checks */
333223f8911SDavidlohr Bueso 	for (i = 0; i < check_loops; i++) {
334910a742dSMichel Lespinasse 		init();
335223f8911SDavidlohr Bueso 		for (j = 0; j < nnodes; j++) {
336910a742dSMichel Lespinasse 			check(j);
337910a742dSMichel Lespinasse 			insert(nodes + j, &root);
338910a742dSMichel Lespinasse 		}
339223f8911SDavidlohr Bueso 		for (j = 0; j < nnodes; j++) {
340223f8911SDavidlohr Bueso 			check(nnodes - j);
341910a742dSMichel Lespinasse 			erase(nodes + j, &root);
342910a742dSMichel Lespinasse 		}
343910a742dSMichel Lespinasse 		check(0);
344910a742dSMichel Lespinasse 	}
345910a742dSMichel Lespinasse 
346dadf9353SMichel Lespinasse 	printk(KERN_ALERT "augmented rbtree testing");
347dadf9353SMichel Lespinasse 
348dadf9353SMichel Lespinasse 	init();
349dadf9353SMichel Lespinasse 
350dadf9353SMichel Lespinasse 	time1 = get_cycles();
351dadf9353SMichel Lespinasse 
352223f8911SDavidlohr Bueso 	for (i = 0; i < perf_loops; i++) {
353223f8911SDavidlohr Bueso 		for (j = 0; j < nnodes; j++)
354dadf9353SMichel Lespinasse 			insert_augmented(nodes + j, &root);
355223f8911SDavidlohr Bueso 		for (j = 0; j < nnodes; j++)
356dadf9353SMichel Lespinasse 			erase_augmented(nodes + j, &root);
357dadf9353SMichel Lespinasse 	}
358dadf9353SMichel Lespinasse 
359dadf9353SMichel Lespinasse 	time2 = get_cycles();
360dadf9353SMichel Lespinasse 	time = time2 - time1;
361dadf9353SMichel Lespinasse 
362223f8911SDavidlohr Bueso 	time = div_u64(time, perf_loops);
363977bd8d5SDavidlohr Bueso 	printk(" -> test 1 (latency of nnodes insert+delete): %llu cycles\n", (unsigned long long)time);
364dadf9353SMichel Lespinasse 
365b10d43f9SDavidlohr Bueso 	time1 = get_cycles();
366b10d43f9SDavidlohr Bueso 
367b10d43f9SDavidlohr Bueso 	for (i = 0; i < perf_loops; i++) {
368b10d43f9SDavidlohr Bueso 		for (j = 0; j < nnodes; j++)
369b10d43f9SDavidlohr Bueso 			insert_augmented_cached(nodes + j, &root);
370b10d43f9SDavidlohr Bueso 		for (j = 0; j < nnodes; j++)
371b10d43f9SDavidlohr Bueso 			erase_augmented_cached(nodes + j, &root);
372b10d43f9SDavidlohr Bueso 	}
373b10d43f9SDavidlohr Bueso 
374b10d43f9SDavidlohr Bueso 	time2 = get_cycles();
375b10d43f9SDavidlohr Bueso 	time = time2 - time1;
376b10d43f9SDavidlohr Bueso 
377b10d43f9SDavidlohr Bueso 	time = div_u64(time, perf_loops);
378b10d43f9SDavidlohr Bueso 	printk(" -> test 2 (latency of nnodes cached insert+delete): %llu cycles\n", (unsigned long long)time);
379b10d43f9SDavidlohr Bueso 
380223f8911SDavidlohr Bueso 	for (i = 0; i < check_loops; i++) {
381dadf9353SMichel Lespinasse 		init();
382223f8911SDavidlohr Bueso 		for (j = 0; j < nnodes; j++) {
383dadf9353SMichel Lespinasse 			check_augmented(j);
384dadf9353SMichel Lespinasse 			insert_augmented(nodes + j, &root);
385dadf9353SMichel Lespinasse 		}
386223f8911SDavidlohr Bueso 		for (j = 0; j < nnodes; j++) {
387223f8911SDavidlohr Bueso 			check_augmented(nnodes - j);
388dadf9353SMichel Lespinasse 			erase_augmented(nodes + j, &root);
389dadf9353SMichel Lespinasse 		}
390dadf9353SMichel Lespinasse 		check_augmented(0);
391dadf9353SMichel Lespinasse 	}
392dadf9353SMichel Lespinasse 
393223f8911SDavidlohr Bueso 	kfree(nodes);
394223f8911SDavidlohr Bueso 
395910a742dSMichel Lespinasse 	return -EAGAIN; /* Fail will directly unload the module */
396910a742dSMichel Lespinasse }
397910a742dSMichel Lespinasse 
rbtree_test_exit(void)398c75aaa8eSDavidlohr Bueso static void __exit rbtree_test_exit(void)
399910a742dSMichel Lespinasse {
400910a742dSMichel Lespinasse 	printk(KERN_ALERT "test exit\n");
401910a742dSMichel Lespinasse }
402910a742dSMichel Lespinasse 
403910a742dSMichel Lespinasse module_init(rbtree_test_init)
404910a742dSMichel Lespinasse module_exit(rbtree_test_exit)
405910a742dSMichel Lespinasse 
406910a742dSMichel Lespinasse MODULE_LICENSE("GPL");
407910a742dSMichel Lespinasse MODULE_AUTHOR("Michel Lespinasse");
408910a742dSMichel Lespinasse MODULE_DESCRIPTION("Red Black Tree test");
409