call_rcu: register work threads as rcu readers
[urcu.git] / urcu-call-rcu-impl.h
index 8a89295fa44bcc6dc18b84e671ec42705128ff06..38cc00190f018cf1afd7fac07e42bcedec484af3 100644 (file)
@@ -31,7 +31,6 @@
 #include <errno.h>
 #include <poll.h>
 #include <sys/time.h>
-#include <syscall.h>
 #include <unistd.h>
 #include <sched.h>
 
@@ -89,26 +88,6 @@ static struct call_rcu_data *default_call_rcu_data;
 static struct call_rcu_data **per_cpu_call_rcu_data;
 static long maxcpus;
 
-static void call_rcu_wait(struct call_rcu_data *crdp)
-{
-       /* Read call_rcu list before read futex */
-       cmm_smp_mb();
-       if (uatomic_read(&crdp->futex) == -1)
-               futex_async(&crdp->futex, FUTEX_WAIT, -1,
-                     NULL, NULL, 0);
-}
-
-static void call_rcu_wake_up(struct call_rcu_data *crdp)
-{
-       /* Write to call_rcu list before reading/writing futex */
-       cmm_smp_mb();
-       if (unlikely(uatomic_read(&crdp->futex) == -1)) {
-               uatomic_set(&crdp->futex, 0);
-               futex_async(&crdp->futex, FUTEX_WAKE, 1,
-                     NULL, NULL, 0);
-       }
-}
-
 /* Allocate the array if it has not already been allocated. */
 
 static void alloc_cpu_call_rcu_data(void)
@@ -136,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)
@@ -195,6 +179,26 @@ int set_thread_cpu_affinity(struct call_rcu_data *crdp)
 }
 #endif
 
+static void call_rcu_wait(struct call_rcu_data *crdp)
+{
+       /* Read call_rcu list before read futex */
+       cmm_smp_mb();
+       if (uatomic_read(&crdp->futex) == -1)
+               futex_async(&crdp->futex, FUTEX_WAIT, -1,
+                     NULL, NULL, 0);
+}
+
+static void call_rcu_wake_up(struct call_rcu_data *crdp)
+{
+       /* Write to call_rcu list before reading/writing futex */
+       cmm_smp_mb();
+       if (unlikely(uatomic_read(&crdp->futex) == -1)) {
+               uatomic_set(&crdp->futex, 0);
+               futex_async(&crdp->futex, FUTEX_WAKE, 1,
+                     NULL, NULL, 0);
+       }
+}
+
 /* This is the code run by each call_rcu thread. */
 
 static void *call_rcu_thread(void *arg)
@@ -211,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);
@@ -243,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)) {
@@ -260,6 +270,7 @@ static void *call_rcu_thread(void *arg)
                } else {
                        poll(NULL, 0, 10);
                }
+               rcu_thread_online();
        }
        if (!rt) {
                /*
@@ -269,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;
 }
 
This page took 0.02381 seconds and 4 git commands to generate.