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