diff options
-rw-r--r-- | lib/radix-tree.c | 4 | ||||
-rw-r--r-- | tools/testing/radix-tree/Makefile | 1 | ||||
-rw-r--r-- | tools/testing/radix-tree/main.c | 1 | ||||
-rw-r--r-- | tools/testing/radix-tree/regression.h | 1 | ||||
-rw-r--r-- | tools/testing/radix-tree/regression4.c | 79 |
5 files changed, 84 insertions, 2 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 1106bb6aa01e..14d51548bea6 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -784,11 +784,11 @@ void *__radix_tree_lookup(const struct radix_tree_root *root, | |||
784 | while (radix_tree_is_internal_node(node)) { | 784 | while (radix_tree_is_internal_node(node)) { |
785 | unsigned offset; | 785 | unsigned offset; |
786 | 786 | ||
787 | if (node == RADIX_TREE_RETRY) | ||
788 | goto restart; | ||
789 | parent = entry_to_node(node); | 787 | parent = entry_to_node(node); |
790 | offset = radix_tree_descend(parent, &node, index); | 788 | offset = radix_tree_descend(parent, &node, index); |
791 | slot = parent->slots + offset; | 789 | slot = parent->slots + offset; |
790 | if (node == RADIX_TREE_RETRY) | ||
791 | goto restart; | ||
792 | if (parent->shift == 0) | 792 | if (parent->shift == 0) |
793 | break; | 793 | break; |
794 | } | 794 | } |
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile index acf1afa01c5b..397d6b612502 100644 --- a/tools/testing/radix-tree/Makefile +++ b/tools/testing/radix-tree/Makefile | |||
@@ -7,6 +7,7 @@ LDLIBS+= -lpthread -lurcu | |||
7 | TARGETS = main idr-test multiorder xarray | 7 | TARGETS = main idr-test multiorder xarray |
8 | CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o bitmap.o | 8 | CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o bitmap.o |
9 | OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \ | 9 | OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \ |
10 | regression4.o \ | ||
10 | tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o | 11 | tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o |
11 | 12 | ||
12 | ifndef SHIFT | 13 | ifndef SHIFT |
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c index 77a44c54998f..7a22d6e3732e 100644 --- a/tools/testing/radix-tree/main.c +++ b/tools/testing/radix-tree/main.c | |||
@@ -308,6 +308,7 @@ int main(int argc, char **argv) | |||
308 | regression1_test(); | 308 | regression1_test(); |
309 | regression2_test(); | 309 | regression2_test(); |
310 | regression3_test(); | 310 | regression3_test(); |
311 | regression4_test(); | ||
311 | iteration_test(0, 10 + 90 * long_run); | 312 | iteration_test(0, 10 + 90 * long_run); |
312 | iteration_test(7, 10 + 90 * long_run); | 313 | iteration_test(7, 10 + 90 * long_run); |
313 | single_thread_tests(long_run); | 314 | single_thread_tests(long_run); |
diff --git a/tools/testing/radix-tree/regression.h b/tools/testing/radix-tree/regression.h index 3c8a1584e9ee..135145af18b7 100644 --- a/tools/testing/radix-tree/regression.h +++ b/tools/testing/radix-tree/regression.h | |||
@@ -5,5 +5,6 @@ | |||
5 | void regression1_test(void); | 5 | void regression1_test(void); |
6 | void regression2_test(void); | 6 | void regression2_test(void); |
7 | void regression3_test(void); | 7 | void regression3_test(void); |
8 | void regression4_test(void); | ||
8 | 9 | ||
9 | #endif | 10 | #endif |
diff --git a/tools/testing/radix-tree/regression4.c b/tools/testing/radix-tree/regression4.c new file mode 100644 index 000000000000..cf4e5aba6b08 --- /dev/null +++ b/tools/testing/radix-tree/regression4.c | |||
@@ -0,0 +1,79 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | #include <linux/kernel.h> | ||
3 | #include <linux/gfp.h> | ||
4 | #include <linux/slab.h> | ||
5 | #include <linux/radix-tree.h> | ||
6 | #include <linux/rcupdate.h> | ||
7 | #include <stdlib.h> | ||
8 | #include <pthread.h> | ||
9 | #include <stdio.h> | ||
10 | #include <assert.h> | ||
11 | |||
12 | #include "regression.h" | ||
13 | |||
14 | static pthread_barrier_t worker_barrier; | ||
15 | static int obj0, obj1; | ||
16 | static RADIX_TREE(mt_tree, GFP_KERNEL); | ||
17 | |||
18 | static void *reader_fn(void *arg) | ||
19 | { | ||
20 | int i; | ||
21 | void *entry; | ||
22 | |||
23 | rcu_register_thread(); | ||
24 | pthread_barrier_wait(&worker_barrier); | ||
25 | |||
26 | for (i = 0; i < 1000000; i++) { | ||
27 | rcu_read_lock(); | ||
28 | entry = radix_tree_lookup(&mt_tree, 0); | ||
29 | rcu_read_unlock(); | ||
30 | if (entry != &obj0) { | ||
31 | printf("iteration %d bad entry = %p\n", i, entry); | ||
32 | abort(); | ||
33 | } | ||
34 | } | ||
35 | |||
36 | rcu_unregister_thread(); | ||
37 | |||
38 | return NULL; | ||
39 | } | ||
40 | |||
41 | static void *writer_fn(void *arg) | ||
42 | { | ||
43 | int i; | ||
44 | |||
45 | rcu_register_thread(); | ||
46 | pthread_barrier_wait(&worker_barrier); | ||
47 | |||
48 | for (i = 0; i < 1000000; i++) { | ||
49 | radix_tree_insert(&mt_tree, 1, &obj1); | ||
50 | radix_tree_delete(&mt_tree, 1); | ||
51 | } | ||
52 | |||
53 | rcu_unregister_thread(); | ||
54 | |||
55 | return NULL; | ||
56 | } | ||
57 | |||
58 | void regression4_test(void) | ||
59 | { | ||
60 | pthread_t reader, writer; | ||
61 | |||
62 | printv(1, "regression test 4 starting\n"); | ||
63 | |||
64 | radix_tree_insert(&mt_tree, 0, &obj0); | ||
65 | pthread_barrier_init(&worker_barrier, NULL, 2); | ||
66 | |||
67 | if (pthread_create(&reader, NULL, reader_fn, NULL) || | ||
68 | pthread_create(&writer, NULL, writer_fn, NULL)) { | ||
69 | perror("pthread_create"); | ||
70 | exit(1); | ||
71 | } | ||
72 | |||
73 | if (pthread_join(reader, NULL) || pthread_join(writer, NULL)) { | ||
74 | perror("pthread_join"); | ||
75 | exit(1); | ||
76 | } | ||
77 | |||
78 | printv(1, "regression test 4 passed\n"); | ||
79 | } | ||