1#include <linux/rcupdate.h> 2#include <pthread.h> 3#include <stdio.h> 4#include <assert.h> 5 6static pthread_mutex_t rculock = PTHREAD_MUTEX_INITIALIZER; 7static struct rcu_head *rcuhead_global = NULL; 8static __thread int nr_rcuhead = 0; 9static __thread struct rcu_head *rcuhead = NULL; 10static __thread struct rcu_head *rcutail = NULL; 11 12static pthread_cond_t rcu_worker_cond = PTHREAD_COND_INITIALIZER; 13 14/* switch to urcu implementation when it is merged. */ 15void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *head)) 16{ 17 head->func = func; 18 head->next = rcuhead; 19 rcuhead = head; 20 if (!rcutail) 21 rcutail = head; 22 nr_rcuhead++; 23 if (nr_rcuhead >= 1000) { 24 int signal = 0; 25 26 pthread_mutex_lock(&rculock); 27 if (!rcuhead_global) 28 signal = 1; 29 rcutail->next = rcuhead_global; 30 rcuhead_global = head; 31 pthread_mutex_unlock(&rculock); 32 33 nr_rcuhead = 0; 34 rcuhead = NULL; 35 rcutail = NULL; 36 37 if (signal) { 38 pthread_cond_signal(&rcu_worker_cond); 39 } 40 } 41} 42 43static void *rcu_worker(void *arg) 44{ 45 struct rcu_head *r; 46 47 rcupdate_thread_init(); 48 49 while (1) { 50 pthread_mutex_lock(&rculock); 51 while (!rcuhead_global) { 52 pthread_cond_wait(&rcu_worker_cond, &rculock); 53 } 54 r = rcuhead_global; 55 rcuhead_global = NULL; 56 57 pthread_mutex_unlock(&rculock); 58 59 synchronize_rcu(); 60 61 while (r) { 62 struct rcu_head *tmp = r->next; 63 r->func(r); 64 r = tmp; 65 } 66 } 67 68 rcupdate_thread_exit(); 69 70 return NULL; 71} 72 73static pthread_t worker_thread; 74void rcupdate_init(void) 75{ 76 pthread_create(&worker_thread, NULL, rcu_worker, NULL); 77} 78 79void rcupdate_thread_init(void) 80{ 81 rcu_register_thread(); 82} 83void rcupdate_thread_exit(void) 84{ 85 rcu_unregister_thread(); 86} 87