linux/tools/testing/radix-tree/rcupdate.c
<<
>>
Prefs
   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