diff options
-rw-r--r-- | tools/testing/radix-tree/multiorder.c | 63 | ||||
-rw-r--r-- | tools/testing/radix-tree/test.h | 1 |
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 | ||
628 | bool stop_iteration = false; | ||
629 | |||
630 | static 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 | |||
646 | static 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 | |||
672 | static 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 | |||
627 | void multiorder_checks(void) | 689 | void 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 { | |||
13 | struct item *item_create(unsigned long index, unsigned int order); | 13 | struct item *item_create(unsigned long index, unsigned int order); |
14 | int __item_insert(struct radix_tree_root *root, struct item *item); | 14 | int __item_insert(struct radix_tree_root *root, struct item *item); |
15 | int item_insert(struct radix_tree_root *root, unsigned long index); | 15 | int item_insert(struct radix_tree_root *root, unsigned long index); |
16 | void item_sanity(struct item *item, unsigned long index); | ||
16 | int item_insert_order(struct radix_tree_root *root, unsigned long index, | 17 | int item_insert_order(struct radix_tree_root *root, unsigned long index, |
17 | unsigned order); | 18 | unsigned order); |
18 | int item_delete(struct radix_tree_root *root, unsigned long index); | 19 | int item_delete(struct radix_tree_root *root, unsigned long index); |