| // 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"); | 
 | } |