diff options
Diffstat (limited to 'tools/testing/radix-tree/regression4.c')
| -rw-r--r-- | tools/testing/radix-tree/regression4.c | 79 | 
1 files changed, 79 insertions, 0 deletions
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 @@ +// SPDX-License-Identifier: GPL-2.0 +#include <linux/kernel.h> +#include <linux/gfp.h> +#include <linux/slab.h> +#include <linux/radix-tree.h> +#include <linux/rcupdate.h> +#include <stdlib.h> +#include <pthread.h> +#include <stdio.h> +#include <assert.h> + +#include "regression.h" + +static pthread_barrier_t worker_barrier; +static int obj0, obj1; +static RADIX_TREE(mt_tree, GFP_KERNEL); + +static void *reader_fn(void *arg) +{ +	int i; +	void *entry; + +	rcu_register_thread(); +	pthread_barrier_wait(&worker_barrier); + +	for (i = 0; i < 1000000; i++) { +		rcu_read_lock(); +		entry = radix_tree_lookup(&mt_tree, 0); +		rcu_read_unlock(); +		if (entry != &obj0) { +			printf("iteration %d bad entry = %p\n", i, entry); +			abort(); +		} +	} + +	rcu_unregister_thread(); + +	return NULL; +} + +static void *writer_fn(void *arg) +{ +	int i; + +	rcu_register_thread(); +	pthread_barrier_wait(&worker_barrier); + +	for (i = 0; i < 1000000; i++) { +		radix_tree_insert(&mt_tree, 1, &obj1); +		radix_tree_delete(&mt_tree, 1); +	} + +	rcu_unregister_thread(); + +	return NULL; +} + +void regression4_test(void) +{ +	pthread_t reader, writer; + +	printv(1, "regression test 4 starting\n"); + +	radix_tree_insert(&mt_tree, 0, &obj0); +	pthread_barrier_init(&worker_barrier, NULL, 2); + +	if (pthread_create(&reader, NULL, reader_fn, NULL) || +	    pthread_create(&writer, NULL, writer_fn, NULL)) { +		perror("pthread_create"); +		exit(1); +	} + +	if (pthread_join(reader, NULL) || pthread_join(writer, NULL)) { +		perror("pthread_join"); +		exit(1); +	} + +	printv(1, "regression test 4 passed\n"); +}  | 
