Fix: rculfhash: urcu_die() takes positive error value
[userspace-rcu.git] / src / urcu-qsbr.c
index d69d93b1018e2740a0bf9f6fec877a012820f1e8..318ab29c6e34afbd6957b90916c3cf84e03fe1bf 100644 (file)
@@ -53,6 +53,7 @@
 #define _LGPL_SOURCE
 
 void __attribute__((destructor)) urcu_qsbr_exit(void);
+static void urcu_call_rcu_exit(void);
 
 /*
  * rcu_gp_lock ensures mutual exclusion between threads calling
@@ -123,17 +124,25 @@ static void wait_gp(void)
 {
        /* Read reader_gp before read futex */
        cmm_smp_rmb();
-       if (uatomic_read(&urcu_qsbr_gp.futex) != -1)
-               return;
-       while (futex_noasync(&urcu_qsbr_gp.futex, FUTEX_WAIT, -1,
-                       NULL, NULL, 0)) {
+       while (uatomic_read(&urcu_qsbr_gp.futex) == -1) {
+               if (!futex_noasync(&urcu_qsbr_gp.futex, FUTEX_WAIT, -1, NULL, NULL, 0)) {
+                       /*
+                        * Prior queued wakeups queued by unrelated code
+                        * using the same address can cause futex wait to
+                        * return 0 even through the futex value is still
+                        * -1 (spurious wakeups). Check the value again
+                        * in user-space to validate whether it really
+                        * differs from -1.
+                        */
+                       continue;
+               }
                switch (errno) {
-               case EWOULDBLOCK:
+               case EAGAIN:
                        /* Value already changed. */
                        return;
                case EINTR:
                        /* Retry if interrupted by signal. */
-                       break;  /* Get out of switch. */
+                       break;  /* Get out of switch. Check again. */
                default:
                        /* Unexpected error. */
                        urcu_die(errno);
@@ -501,9 +510,11 @@ void urcu_qsbr_exit(void)
         * readers, and left running at exit.
         * urcu_posix_assert(cds_list_empty(&registry));
         */
+       urcu_call_rcu_exit();
 }
 
 DEFINE_RCU_FLAVOR(rcu_flavor);
 
 #include "urcu-call-rcu-impl.h"
 #include "urcu-defer-impl.h"
+#include "urcu-poll-impl.h"
This page took 0.022934 seconds and 4 git commands to generate.