Make defer_rcu() usable from library using multiple URCU implementations
[urcu.git] / urcu-bp.c
index 136f97d3cf6746eef6d39a9f2a22ca1139a342fc..14b200129fe42656ae11e178aa0d3c6442f26061 100644 (file)
--- a/urcu-bp.c
+++ b/urcu-bp.c
@@ -35,6 +35,8 @@
 #include <unistd.h>
 #include <sys/mman.h>
 
+#include "urcu-bp-map.h"
+
 #include "urcu-bp-static.h"
 /* Do not #define _LGPL_SOURCE to ensure we can emit the wrapper symbols */
 #include "urcu-bp.h"
@@ -76,6 +78,9 @@ struct registry_arena {
 
 static struct registry_arena registry_arena;
 
+/* Saved fork signal mask, protected by rcu_gp_lock */
+static sigset_t saved_fork_signal_mask;
+
 static void rcu_gc_registry(void);
 
 static void mutex_lock(pthread_mutex_t *mutex)
@@ -95,11 +100,6 @@ static void mutex_lock(pthread_mutex_t *mutex)
                        perror("Error in pthread mutex lock");
                        exit(-1);
                }
-               if (rcu_reader.need_mb) {
-                       cmm_smp_mb();
-                       rcu_reader.need_mb = 0;
-                       cmm_smp_mb();
-               }
                poll(NULL,0,10);
        }
 #endif /* #else #ifndef DISTRUST_SIGNALS_EXTREME */
@@ -123,13 +123,13 @@ void update_counter_and_wait(void)
        struct rcu_reader *index, *tmp;
 
        /* Switch parity: 0 -> 1, 1 -> 0 */
-       CAA_STORE_SHARED(rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR_PHASE);
+       CMM_STORE_SHARED(rcu_gp_ctr, rcu_gp_ctr ^ RCU_GP_CTR_PHASE);
 
        /*
         * Must commit qparity update to memory before waiting for other parity
         * quiescent state. Failure to do so could result in the writer waiting
         * forever while new readers are always accessing data (no progress).
-        * Ensured by CAA_STORE_SHARED and CAA_LOAD_SHARED.
+        * Ensured by CMM_STORE_SHARED and CMM_LOAD_SHARED.
         */
 
        /*
@@ -336,3 +336,47 @@ void rcu_bp_exit()
 {
        munmap(registry_arena.p, registry_arena.len);
 }
+
+/*
+ * Holding the rcu_gp_lock across fork will make sure we fork() don't race with
+ * a concurrent thread executing with this same lock held. This ensures that the
+ * registry is in a coherent state in the child.
+ */
+void rcu_bp_before_fork(void)
+{
+       sigset_t newmask, oldmask;
+       int ret;
+
+       ret = sigemptyset(&newmask);
+       assert(!ret);
+       ret = pthread_sigmask(SIG_SETMASK, &newmask, &oldmask);
+       assert(!ret);
+       mutex_lock(&rcu_gp_lock);
+       saved_fork_signal_mask = oldmask;
+}
+
+void rcu_bp_after_fork_parent(void)
+{
+       sigset_t oldmask;
+       int ret;
+
+       oldmask = saved_fork_signal_mask;
+       mutex_unlock(&rcu_gp_lock);
+       ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
+       assert(!ret);
+}
+
+void rcu_bp_after_fork_child(void)
+{
+       sigset_t oldmask;
+       int ret;
+
+       rcu_gc_registry();
+       oldmask = saved_fork_signal_mask;
+       mutex_unlock(&rcu_gp_lock);
+       ret = pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
+       assert(!ret);
+}
+
+#include "urcu-call-rcu-impl.h"
+#include "urcu-defer-impl.h"
This page took 0.023354 seconds and 4 git commands to generate.