1eff3860bSMatthew Wilcox // SPDX-License-Identifier: GPL-2.0
2eff3860bSMatthew Wilcox #include <linux/kernel.h>
3eff3860bSMatthew Wilcox #include <linux/gfp.h>
4eff3860bSMatthew Wilcox #include <linux/slab.h>
5eff3860bSMatthew Wilcox #include <linux/radix-tree.h>
6eff3860bSMatthew Wilcox #include <linux/rcupdate.h>
7eff3860bSMatthew Wilcox #include <stdlib.h>
8eff3860bSMatthew Wilcox #include <pthread.h>
9eff3860bSMatthew Wilcox #include <stdio.h>
10eff3860bSMatthew Wilcox #include <assert.h>
11eff3860bSMatthew Wilcox 
12eff3860bSMatthew Wilcox #include "regression.h"
13eff3860bSMatthew Wilcox 
14eff3860bSMatthew Wilcox static pthread_barrier_t worker_barrier;
15eff3860bSMatthew Wilcox static int obj0, obj1;
16eff3860bSMatthew Wilcox static RADIX_TREE(mt_tree, GFP_KERNEL);
17eff3860bSMatthew Wilcox 
reader_fn(void * arg)18eff3860bSMatthew Wilcox static void *reader_fn(void *arg)
19eff3860bSMatthew Wilcox {
20eff3860bSMatthew Wilcox 	int i;
21eff3860bSMatthew Wilcox 	void *entry;
22eff3860bSMatthew Wilcox 
23eff3860bSMatthew Wilcox 	rcu_register_thread();
24eff3860bSMatthew Wilcox 	pthread_barrier_wait(&worker_barrier);
25eff3860bSMatthew Wilcox 
26eff3860bSMatthew Wilcox 	for (i = 0; i < 1000000; i++) {
27eff3860bSMatthew Wilcox 		rcu_read_lock();
28eff3860bSMatthew Wilcox 		entry = radix_tree_lookup(&mt_tree, 0);
29eff3860bSMatthew Wilcox 		rcu_read_unlock();
30eff3860bSMatthew Wilcox 		if (entry != &obj0) {
31eff3860bSMatthew Wilcox 			printf("iteration %d bad entry = %p\n", i, entry);
32eff3860bSMatthew Wilcox 			abort();
33eff3860bSMatthew Wilcox 		}
34eff3860bSMatthew Wilcox 	}
35eff3860bSMatthew Wilcox 
36eff3860bSMatthew Wilcox 	rcu_unregister_thread();
37eff3860bSMatthew Wilcox 
38eff3860bSMatthew Wilcox 	return NULL;
39eff3860bSMatthew Wilcox }
40eff3860bSMatthew Wilcox 
writer_fn(void * arg)41eff3860bSMatthew Wilcox static void *writer_fn(void *arg)
42eff3860bSMatthew Wilcox {
43eff3860bSMatthew Wilcox 	int i;
44eff3860bSMatthew Wilcox 
45eff3860bSMatthew Wilcox 	rcu_register_thread();
46eff3860bSMatthew Wilcox 	pthread_barrier_wait(&worker_barrier);
47eff3860bSMatthew Wilcox 
48eff3860bSMatthew Wilcox 	for (i = 0; i < 1000000; i++) {
49eff3860bSMatthew Wilcox 		radix_tree_insert(&mt_tree, 1, &obj1);
50eff3860bSMatthew Wilcox 		radix_tree_delete(&mt_tree, 1);
51eff3860bSMatthew Wilcox 	}
52eff3860bSMatthew Wilcox 
53eff3860bSMatthew Wilcox 	rcu_unregister_thread();
54eff3860bSMatthew Wilcox 
55eff3860bSMatthew Wilcox 	return NULL;
56eff3860bSMatthew Wilcox }
57eff3860bSMatthew Wilcox 
regression4_test(void)58eff3860bSMatthew Wilcox void regression4_test(void)
59eff3860bSMatthew Wilcox {
60eff3860bSMatthew Wilcox 	pthread_t reader, writer;
61eff3860bSMatthew Wilcox 
62eff3860bSMatthew Wilcox 	printv(1, "regression test 4 starting\n");
63eff3860bSMatthew Wilcox 
64eff3860bSMatthew Wilcox 	radix_tree_insert(&mt_tree, 0, &obj0);
65eff3860bSMatthew Wilcox 	pthread_barrier_init(&worker_barrier, NULL, 2);
66eff3860bSMatthew Wilcox 
67eff3860bSMatthew Wilcox 	if (pthread_create(&reader, NULL, reader_fn, NULL) ||
68eff3860bSMatthew Wilcox 	    pthread_create(&writer, NULL, writer_fn, NULL)) {
69eff3860bSMatthew Wilcox 		perror("pthread_create");
70eff3860bSMatthew Wilcox 		exit(1);
71eff3860bSMatthew Wilcox 	}
72eff3860bSMatthew Wilcox 
73eff3860bSMatthew Wilcox 	if (pthread_join(reader, NULL) || pthread_join(writer, NULL)) {
74eff3860bSMatthew Wilcox 		perror("pthread_join");
75eff3860bSMatthew Wilcox 		exit(1);
76eff3860bSMatthew Wilcox 	}
77eff3860bSMatthew Wilcox 
78eff3860bSMatthew Wilcox 	printv(1, "regression test 4 passed\n");
79eff3860bSMatthew Wilcox }
80