diff options
Diffstat (limited to 'tools/testing/radix-tree/multiorder.c')
| -rw-r--r-- | tools/testing/radix-tree/multiorder.c | 63 | 
1 files changed, 63 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 @@  #include <linux/radix-tree.h>  #include <linux/slab.h>  #include <linux/errno.h> +#include <pthread.h>  #include "test.h" @@ -624,6 +625,67 @@ static void multiorder_account(void)  	item_kill_tree(&tree);  } +bool stop_iteration = false; + +static void *creator_func(void *ptr) +{ +	/* 'order' is set up to ensure we have sibling entries */ +	unsigned int order = RADIX_TREE_MAP_SHIFT - 1; +	struct radix_tree_root *tree = ptr; +	int i; + +	for (i = 0; i < 10000; i++) { +		item_insert_order(tree, 0, order); +		item_delete_rcu(tree, 0); +	} + +	stop_iteration = true; +	return NULL; +} + +static void *iterator_func(void *ptr) +{ +	struct radix_tree_root *tree = ptr; +	struct radix_tree_iter iter; +	struct item *item; +	void **slot; + +	while (!stop_iteration) { +		rcu_read_lock(); +		radix_tree_for_each_slot(slot, tree, &iter, 0) { +			item = radix_tree_deref_slot(slot); + +			if (!item) +				continue; +			if (radix_tree_deref_retry(item)) { +				slot = radix_tree_iter_retry(&iter); +				continue; +			} + +			item_sanity(item, iter.index); +		} +		rcu_read_unlock(); +	} +	return NULL; +} + +static void multiorder_iteration_race(void) +{ +	const int num_threads = sysconf(_SC_NPROCESSORS_ONLN); +	pthread_t worker_thread[num_threads]; +	RADIX_TREE(tree, GFP_KERNEL); +	int i; + +	pthread_create(&worker_thread[0], NULL, &creator_func, &tree); +	for (i = 1; i < num_threads; i++) +		pthread_create(&worker_thread[i], NULL, &iterator_func, &tree); + +	for (i = 0; i < num_threads; i++) +		pthread_join(worker_thread[i], NULL); + +	item_kill_tree(&tree); +} +  void multiorder_checks(void)  {  	int i; @@ -644,6 +706,7 @@ void multiorder_checks(void)  	multiorder_join();  	multiorder_split();  	multiorder_account(); +	multiorder_iteration_race();  	radix_tree_cpu_dead(0);  } | 
