init maxcpus before use
[urcu.git] / urcu-call-rcu-impl.h
index d5baa69685387808044529f634a69157ca9126c0..e0a8fd883ee4a24782b3464a970f20be645b5fdc 100644 (file)
@@ -115,7 +115,12 @@ static void alloc_cpu_call_rcu_data(void)
 
 #else /* #if defined(HAVE_SCHED_GETCPU) && defined(HAVE_SYSCONF) */
 
-static const struct call_rcu_data **per_cpu_call_rcu_data = NULL;
+/*
+ * per_cpu_call_rcu_data should be constant, but some functions below, used both
+ * for cases where cpu number is available and not available, assume it it not
+ * constant.
+ */
+static struct call_rcu_data **per_cpu_call_rcu_data = NULL;
 static const long maxcpus = -1;
 
 static void alloc_cpu_call_rcu_data(void)
@@ -210,6 +215,11 @@ static void *call_rcu_thread(void *arg)
                exit(-1);
        }
 
+       /*
+        * If callbacks take a read-side lock, we need to be registered.
+        */
+       rcu_register_thread();
+
        thread_call_rcu_data = crdp;
        if (!rt) {
                uatomic_dec(&crdp->futex);
@@ -242,6 +252,7 @@ static void *call_rcu_thread(void *arg)
                }
                if (uatomic_read(&crdp->flags) & URCU_CALL_RCU_STOP)
                        break;
+               rcu_thread_offline();
                if (!rt) {
                        if (&crdp->cbs.head
                            == _CMM_LOAD_SHARED(crdp->cbs.tail)) {
@@ -259,6 +270,7 @@ static void *call_rcu_thread(void *arg)
                } else {
                        poll(NULL, 0, 10);
                }
+               rcu_thread_online();
        }
        if (!rt) {
                /*
@@ -268,6 +280,7 @@ static void *call_rcu_thread(void *arg)
                uatomic_set(&crdp->futex, 0);
        }
        uatomic_or(&crdp->flags, URCU_CALL_RCU_STOPPED);
+       rcu_unregister_thread();
        return NULL;
 }
 
@@ -370,9 +383,10 @@ struct call_rcu_data *create_call_rcu_data(unsigned long flags,
 
 int set_cpu_call_rcu_data(int cpu, struct call_rcu_data *crdp)
 {
-       int warned = 0;
+       static int warned = 0;
 
        call_rcu_lock(&call_rcu_mutex);
+       alloc_cpu_call_rcu_data();
        if (cpu < 0 || maxcpus <= cpu) {
                if (!warned) {
                        fprintf(stderr, "[error] liburcu: set CPU # out of range\n");
@@ -382,7 +396,6 @@ int set_cpu_call_rcu_data(int cpu, struct call_rcu_data *crdp)
                errno = EINVAL;
                return -EINVAL;
        }
-       alloc_cpu_call_rcu_data();
        call_rcu_unlock(&call_rcu_mutex);
        if (per_cpu_call_rcu_data == NULL) {
                errno = ENOMEM;
@@ -469,7 +482,9 @@ void set_thread_call_rcu_data(struct call_rcu_data *crdp)
 /*
  * Create a separate call_rcu thread for each CPU.  This does not
  * replace a pre-existing call_rcu thread -- use the set_cpu_call_rcu_data()
- * function if you want that behavior.
+ * function if you want that behavior. Should be paired with
+ * free_all_cpu_call_rcu_data() to teardown these call_rcu worker
+ * threads.
  */
 
 int create_all_cpu_call_rcu_data(unsigned long flags)
This page took 0.024076 seconds and 4 git commands to generate.