diff options
| author | Matthew Wilcox <willy@linux.intel.com> | 2016-03-17 14:21:45 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-17 15:09:34 -0700 | 
| commit | 1366c37ed84b166a0fffe201154b0d3b78a3976b (patch) | |
| tree | 3a688edaf09069694db90421f200568b886a4295 /tools/testing/radix-tree/rcupdate.c | |
| parent | f67c07f07fca95a7f330b8bb928eabaf9fcce75d (diff) | |
radix tree test harness
This code is mostly from Andrew Morton and Nick Piggin; tarball downloaded
from http://ozlabs.org/~akpm/rtth.tar.gz with sha1sum
0ce679db9ec047296b5d1ff7a1dfaa03a7bef1bd
Some small modifications were necessary to the test harness to fix the
build with the current Linux source code.
I also made minor modifications to automatically test the radix-tree.c
and radix-tree.h files that are in the current source tree, as opposed
to a copied and slightly modified version.  I am sure more could be done
to tidy up the harness, as well as adding more tests.
[koct9i@gmail.com: fix compilation]
Signed-off-by: Matthew Wilcox <willy@linux.intel.com>
Cc: Shuah Khan <shuahkh@osg.samsung.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Matthew Wilcox <willy@linux.intel.com>
Cc: "Kirill A. Shutemov" <kirill.shutemov@linux.intel.com>
Cc: Ross Zwisler <ross.zwisler@linux.intel.com>
Cc: Hugh Dickins <hughd@google.com>
Signed-off-by: Konstantin Khlebnikov <koct9i@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'tools/testing/radix-tree/rcupdate.c')
| -rw-r--r-- | tools/testing/radix-tree/rcupdate.c | 86 | 
1 files changed, 86 insertions, 0 deletions
diff --git a/tools/testing/radix-tree/rcupdate.c b/tools/testing/radix-tree/rcupdate.c new file mode 100644 index 000000000000..31a2d14225d6 --- /dev/null +++ b/tools/testing/radix-tree/rcupdate.c @@ -0,0 +1,86 @@ +#include <linux/rcupdate.h> +#include <pthread.h> +#include <stdio.h> +#include <assert.h> + +static pthread_mutex_t rculock = PTHREAD_MUTEX_INITIALIZER; +static struct rcu_head *rcuhead_global = NULL; +static __thread int nr_rcuhead = 0; +static __thread struct rcu_head *rcuhead = NULL; +static __thread struct rcu_head *rcutail = NULL; + +static pthread_cond_t rcu_worker_cond = PTHREAD_COND_INITIALIZER; + +/* switch to urcu implementation when it is merged. */ +void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *head)) +{ +	head->func = func; +	head->next = rcuhead; +	rcuhead = head; +	if (!rcutail) +		rcutail = head; +	nr_rcuhead++; +	if (nr_rcuhead >= 1000) { +		int signal = 0; + +		pthread_mutex_lock(&rculock); +		if (!rcuhead_global) +			signal = 1; +		rcutail->next = rcuhead_global; +		rcuhead_global = head; +		pthread_mutex_unlock(&rculock); + +		nr_rcuhead = 0; +		rcuhead = NULL; +		rcutail = NULL; + +		if (signal) { +			pthread_cond_signal(&rcu_worker_cond); +		} +	} +} + +static void *rcu_worker(void *arg) +{ +	struct rcu_head *r; + +	rcupdate_thread_init(); + +	while (1) { +		pthread_mutex_lock(&rculock); +		while (!rcuhead_global) { +			pthread_cond_wait(&rcu_worker_cond, &rculock); +		} +		r = rcuhead_global; +		rcuhead_global = NULL; + +		pthread_mutex_unlock(&rculock); + +		synchronize_rcu(); + +		while (r) { +			struct rcu_head *tmp = r->next; +			r->func(r); +			r = tmp; +		} +	} + +	rcupdate_thread_exit(); + +	return NULL; +} + +static pthread_t worker_thread; +void rcupdate_init(void) +{ +	pthread_create(&worker_thread, NULL, rcu_worker, NULL); +} + +void rcupdate_thread_init(void) +{ +	rcu_register_thread(); +} +void rcupdate_thread_exit(void) +{ +	rcu_unregister_thread(); +}  | 
