aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/radix-tree/iteration_check.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/testing/radix-tree/iteration_check.c')
-rw-r--r--tools/testing/radix-tree/iteration_check.c80
1 files changed, 47 insertions, 33 deletions
diff --git a/tools/testing/radix-tree/iteration_check.c b/tools/testing/radix-tree/iteration_check.c
index f328a66899b4..7572b7ed930e 100644
--- a/tools/testing/radix-tree/iteration_check.c
+++ b/tools/testing/radix-tree/iteration_check.c
@@ -16,26 +16,36 @@
16#include <pthread.h> 16#include <pthread.h>
17#include "test.h" 17#include "test.h"
18 18
19#define NUM_THREADS 4 19#define NUM_THREADS 5
20#define TAG 0 20#define MAX_IDX 100
21#define TAG 0
22#define NEW_TAG 1
23
21static pthread_mutex_t tree_lock = PTHREAD_MUTEX_INITIALIZER; 24static pthread_mutex_t tree_lock = PTHREAD_MUTEX_INITIALIZER;
22static pthread_t threads[NUM_THREADS]; 25static pthread_t threads[NUM_THREADS];
23static unsigned int seeds[3]; 26static unsigned int seeds[3];
24RADIX_TREE(tree, GFP_KERNEL); 27static RADIX_TREE(tree, GFP_KERNEL);
25bool test_complete; 28static bool test_complete;
29static int max_order;
26 30
27/* relentlessly fill the tree with tagged entries */ 31/* relentlessly fill the tree with tagged entries */
28static void *add_entries_fn(void *arg) 32static void *add_entries_fn(void *arg)
29{ 33{
30 int pgoff;
31
32 rcu_register_thread(); 34 rcu_register_thread();
33 35
34 while (!test_complete) { 36 while (!test_complete) {
35 for (pgoff = 0; pgoff < 100; pgoff++) { 37 unsigned long pgoff;
38 int order;
39
40 for (pgoff = 0; pgoff < MAX_IDX; pgoff++) {
36 pthread_mutex_lock(&tree_lock); 41 pthread_mutex_lock(&tree_lock);
37 if (item_insert(&tree, pgoff) == 0) 42 for (order = max_order; order >= 0; order--) {
38 item_tag_set(&tree, pgoff, TAG); 43 if (item_insert_order(&tree, pgoff, order)
44 == 0) {
45 item_tag_set(&tree, pgoff, TAG);
46 break;
47 }
48 }
39 pthread_mutex_unlock(&tree_lock); 49 pthread_mutex_unlock(&tree_lock);
40 } 50 }
41 } 51 }
@@ -62,14 +72,7 @@ static void *tagged_iteration_fn(void *arg)
62 while (!test_complete) { 72 while (!test_complete) {
63 rcu_read_lock(); 73 rcu_read_lock();
64 radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) { 74 radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) {
65 void *entry; 75 void *entry = radix_tree_deref_slot(slot);
66 int i;
67
68 /* busy wait to let removals happen */
69 for (i = 0; i < 1000000; i++)
70 ;
71
72 entry = radix_tree_deref_slot(slot);
73 if (unlikely(!entry)) 76 if (unlikely(!entry))
74 continue; 77 continue;
75 78
@@ -110,14 +113,7 @@ static void *untagged_iteration_fn(void *arg)
110 while (!test_complete) { 113 while (!test_complete) {
111 rcu_read_lock(); 114 rcu_read_lock();
112 radix_tree_for_each_slot(slot, &tree, &iter, 0) { 115 radix_tree_for_each_slot(slot, &tree, &iter, 0) {
113 void *entry; 116 void *entry = radix_tree_deref_slot(slot);
114 int i;
115
116 /* busy wait to let removals happen */
117 for (i = 0; i < 1000000; i++)
118 ;
119
120 entry = radix_tree_deref_slot(slot);
121 if (unlikely(!entry)) 117 if (unlikely(!entry))
122 continue; 118 continue;
123 119
@@ -152,7 +148,7 @@ static void *remove_entries_fn(void *arg)
152 while (!test_complete) { 148 while (!test_complete) {
153 int pgoff; 149 int pgoff;
154 150
155 pgoff = rand_r(&seeds[2]) % 100; 151 pgoff = rand_r(&seeds[2]) % MAX_IDX;
156 152
157 pthread_mutex_lock(&tree_lock); 153 pthread_mutex_lock(&tree_lock);
158 item_delete(&tree, pgoff); 154 item_delete(&tree, pgoff);
@@ -164,36 +160,54 @@ static void *remove_entries_fn(void *arg)
164 return NULL; 160 return NULL;
165} 161}
166 162
163static void *tag_entries_fn(void *arg)
164{
165 rcu_register_thread();
166
167 while (!test_complete) {
168 tag_tagged_items(&tree, &tree_lock, 0, MAX_IDX, 10, TAG,
169 NEW_TAG);
170 }
171 rcu_unregister_thread();
172 return NULL;
173}
174
167/* This is a unit test for a bug found by the syzkaller tester */ 175/* This is a unit test for a bug found by the syzkaller tester */
168void iteration_test(void) 176void iteration_test(unsigned order, unsigned test_duration)
169{ 177{
170 int i; 178 int i;
171 179
172 printf("Running iteration tests for 10 seconds\n"); 180 printf("Running %siteration tests for %d seconds\n",
181 order > 0 ? "multiorder " : "", test_duration);
173 182
183 max_order = order;
174 test_complete = false; 184 test_complete = false;
175 185
176 for (i = 0; i < 3; i++) 186 for (i = 0; i < 3; i++)
177 seeds[i] = rand(); 187 seeds[i] = rand();
178 188
179 if (pthread_create(&threads[0], NULL, tagged_iteration_fn, NULL)) { 189 if (pthread_create(&threads[0], NULL, tagged_iteration_fn, NULL)) {
180 perror("pthread_create"); 190 perror("create tagged iteration thread");
181 exit(1); 191 exit(1);
182 } 192 }
183 if (pthread_create(&threads[1], NULL, untagged_iteration_fn, NULL)) { 193 if (pthread_create(&threads[1], NULL, untagged_iteration_fn, NULL)) {
184 perror("pthread_create"); 194 perror("create untagged iteration thread");
185 exit(1); 195 exit(1);
186 } 196 }
187 if (pthread_create(&threads[2], NULL, add_entries_fn, NULL)) { 197 if (pthread_create(&threads[2], NULL, add_entries_fn, NULL)) {
188 perror("pthread_create"); 198 perror("create add entry thread");
189 exit(1); 199 exit(1);
190 } 200 }
191 if (pthread_create(&threads[3], NULL, remove_entries_fn, NULL)) { 201 if (pthread_create(&threads[3], NULL, remove_entries_fn, NULL)) {
192 perror("pthread_create"); 202 perror("create remove entry thread");
203 exit(1);
204 }
205 if (pthread_create(&threads[4], NULL, tag_entries_fn, NULL)) {
206 perror("create tag entry thread");
193 exit(1); 207 exit(1);
194 } 208 }
195 209
196 sleep(10); 210 sleep(test_duration);
197 test_complete = true; 211 test_complete = true;
198 212
199 for (i = 0; i < NUM_THREADS; i++) { 213 for (i = 0; i < NUM_THREADS; i++) {