Fix: rcu_barrier(): uninitialized futex field
[urcu.git] / urcu-call-rcu-impl.h
index fb3568f802f210d2015b9a42e9d20691ee59df4c..f0751f538b4b66c829d4d988b0d5102192ad889b 100644 (file)
@@ -308,6 +308,8 @@ static void *call_rcu_thread(void *arg)
                        uatomic_or(&crdp->flags, URCU_CALL_RCU_PAUSED);
                        while ((uatomic_read(&crdp->flags) & URCU_CALL_RCU_PAUSE) != 0)
                                poll(NULL, 0, 1);
+                       uatomic_and(&crdp->flags, ~URCU_CALL_RCU_PAUSED);
+                       cmm_smp_mb__after_uatomic_and();
                        rcu_register_thread();
                }
 
@@ -786,7 +788,7 @@ void rcu_barrier(void)
 {
        struct call_rcu_data *crdp;
        struct call_rcu_completion completion;
-       int count = 0, work_count = 0;
+       int count = 0;
        int was_online;
 
        /* Put in offline state in QSBR. */
@@ -812,29 +814,19 @@ void rcu_barrier(void)
                count++;
 
        completion.barrier_count = count;
+       completion.futex = 0;
 
        cds_list_for_each_entry(crdp, &call_rcu_data_list, list) {
                struct call_rcu_completion_work *work;
 
                work = calloc(sizeof(*work), 1);
-               if (!work) {
-                       static int warned = 0;
-
-                       if (!warned) {
-                               fprintf(stderr, "[error] liburcu: unable to allocate memory for rcu_barrier()\n");
-                       }
-                       warned = 1;
-                       break;
-               }
+               if (!work)
+                       urcu_die(errno);
                work->completion = &completion;
                _call_rcu(&work->head, _rcu_barrier_complete, crdp);
-               work_count++;
        }
        call_rcu_unlock(&call_rcu_mutex);
 
-       if (work_count != count)
-               uatomic_sub(&completion.barrier_count, count - work_count);
-
        /* Wait for them */
        for (;;) {
                uatomic_dec(&completion.futex);
@@ -883,6 +875,10 @@ void call_rcu_after_fork_parent(void)
 
        cds_list_for_each_entry(crdp, &call_rcu_data_list, list)
                uatomic_and(&crdp->flags, ~URCU_CALL_RCU_PAUSE);
+       cds_list_for_each_entry(crdp, &call_rcu_data_list, list) {
+               while ((uatomic_read(&crdp->flags) & URCU_CALL_RCU_PAUSED) != 0)
+                       poll(NULL, 0, 1);
+       }
        call_rcu_unlock(&call_rcu_mutex);
 }
 
This page took 0.023039 seconds and 4 git commands to generate.