summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/testing/radix-tree/multiorder.c63
-rw-r--r--tools/testing/radix-tree/test.h1
2 files changed, 64 insertions, 0 deletions
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 59245b3d587c..7bf405638b0b 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -16,6 +16,7 @@
16#include <linux/radix-tree.h> 16#include <linux/radix-tree.h>
17#include <linux/slab.h> 17#include <linux/slab.h>
18#include <linux/errno.h> 18#include <linux/errno.h>
19#include <pthread.h>
19 20
20#include "test.h" 21#include "test.h"
21 22
@@ -624,6 +625,67 @@ static void multiorder_account(void)
624 item_kill_tree(&tree); 625 item_kill_tree(&tree);
625} 626}
626 627
628bool stop_iteration = false;
629
630static void *creator_func(void *ptr)
631{
632 /* 'order' is set up to ensure we have sibling entries */
633 unsigned int order = RADIX_TREE_MAP_SHIFT - 1;
634 struct radix_tree_root *tree = ptr;
635 int i;
636
637 for (i = 0; i < 10000; i++) {
638 item_insert_order(tree, 0, order);
639 item_delete_rcu(tree, 0);
640 }
641
642 stop_iteration = true;
643 return NULL;
644}
645
646static void *iterator_func(void *ptr)
647{
648 struct radix_tree_root *tree = ptr;
649 struct radix_tree_iter iter;
650 struct item *item;
651 void **slot;
652
653 while (!stop_iteration) {
654 rcu_read_lock();
655 radix_tree_for_each_slot(slot, tree, &iter, 0) {
656 item = radix_tree_deref_slot(slot);
657
658 if (!item)
659 continue;
660 if (radix_tree_deref_retry(item)) {
661 slot = radix_tree_iter_retry(&iter);
662 continue;
663 }
664
665 item_sanity(item, iter.index);
666 }
667 rcu_read_unlock();
668 }
669 return NULL;
670}
671
672static void multiorder_iteration_race(void)
673{
674 const int num_threads = sysconf(_SC_NPROCESSORS_ONLN);
675 pthread_t worker_thread[num_threads];
676 RADIX_TREE(tree, GFP_KERNEL);
677 int i;
678
679 pthread_create(&worker_thread[0], NULL, &creator_func, &tree);
680 for (i = 1; i < num_threads; i++)
681 pthread_create(&worker_thread[i], NULL, &iterator_func, &tree);
682
683 for (i = 0; i < num_threads; i++)
684 pthread_join(worker_thread[i], NULL);
685
686 item_kill_tree(&tree);
687}
688
627void multiorder_checks(void) 689void multiorder_checks(void)
628{ 690{
629 int i; 691 int i;
@@ -644,6 +706,7 @@ void multiorder_checks(void)
644 multiorder_join(); 706 multiorder_join();
645 multiorder_split(); 707 multiorder_split();
646 multiorder_account(); 708 multiorder_account();
709 multiorder_iteration_race();
647 710
648 radix_tree_cpu_dead(0); 711 radix_tree_cpu_dead(0);
649} 712}
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index 8cf4a7a7f94c..31f1d9b6f506 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -13,6 +13,7 @@ struct item {
13struct item *item_create(unsigned long index, unsigned int order); 13struct item *item_create(unsigned long index, unsigned int order);
14int __item_insert(struct radix_tree_root *root, struct item *item); 14int __item_insert(struct radix_tree_root *root, struct item *item);
15int item_insert(struct radix_tree_root *root, unsigned long index); 15int item_insert(struct radix_tree_root *root, unsigned long index);
16void item_sanity(struct item *item, unsigned long index);
16int item_insert_order(struct radix_tree_root *root, unsigned long index, 17int item_insert_order(struct radix_tree_root *root, unsigned long index,
17 unsigned order); 18 unsigned order);
18int item_delete(struct radix_tree_root *root, unsigned long index); 19int item_delete(struct radix_tree_root *root, unsigned long index);