Implement sched_yield UP support
[urcu.git] / urcu-qsbr.c
index f681c05bf0c05d96860e06cbb8771b11c9e3e829..b42d7c4a42e3a4aa4e334ca457066327e969a85a 100644 (file)
@@ -99,6 +99,9 @@ static void internal_urcu_unlock(void)
        }
 }
 
+/*
+ * synchronize_rcu() waiting. Single thread.
+ */
 static void wait_for_quiescent_state(void)
 {
        struct reader_registry *index;
@@ -109,13 +112,19 @@ static void wait_for_quiescent_state(void)
         * Wait for each thread rcu_reader_qs_gp count to become 0.
         */
        for (index = registry; index < registry + num_readers; index++) {
+               int wait_loops = 0;
+
+               while (rcu_gp_ongoing(index->rcu_reader_qs_gp)) {
+                       if (wait_loops++ == RCU_QS_ACTIVE_ATTEMPTS) {
+                               sched_yield();  /* ideally sched_yield_to() */
+                       } else {
 #ifndef HAS_INCOHERENT_CACHES
-               while (rcu_gp_ongoing(index->rcu_reader_qs_gp))
-                       cpu_relax();
+                               cpu_relax();
 #else /* #ifndef HAS_INCOHERENT_CACHES */
-               while (rcu_gp_ongoing(index->rcu_reader_qs_gp))
-                       smp_mb();
+                               smp_mb();
 #endif /* #else #ifndef HAS_INCOHERENT_CACHES */
+                       }
+               }
        }
 }
 
@@ -155,6 +164,8 @@ void synchronize_rcu(void)
 
        internal_urcu_lock();
 
+       STORE_SHARED(urcu_gp_ctr, urcu_gp_ctr ^ RCU_GP_ONGOING);
+
        switch_next_urcu_qparity();     /* 0 -> 1 */
 
        /*
@@ -193,6 +204,8 @@ void synchronize_rcu(void)
         */
        wait_for_quiescent_state();     /* Wait readers in parity 1 */
 
+       STORE_SHARED(urcu_gp_ctr, urcu_gp_ctr ^ RCU_GP_ONGOING);
+
        internal_urcu_unlock();
 
        /*
@@ -220,8 +233,10 @@ void synchronize_rcu(void)
                STORE_SHARED(rcu_reader_qs_gp, 0);
 
        internal_urcu_lock();
+       STORE_SHARED(urcu_gp_ctr, urcu_gp_ctr ^ RCU_GP_ONGOING);
        STORE_SHARED(urcu_gp_ctr, urcu_gp_ctr + RCU_GP_CTR);
        wait_for_quiescent_state();
+       STORE_SHARED(urcu_gp_ctr, urcu_gp_ctr ^ RCU_GP_ONGOING);
        internal_urcu_unlock();
 
        if (was_online)
@@ -255,6 +270,12 @@ void *rcu_assign_pointer_sym(void **p, void *v)
        return STORE_SHARED(p, v);
 }
 
+void *rcu_cmpxchg_pointer_sym(void **p, void *old, void *_new)
+{
+       wmb();
+       return cmpxchg(p, old, _new);
+}
+
 void *rcu_xchg_pointer_sym(void **p, void *v)
 {
        wmb();
This page took 0.023498 seconds and 4 git commands to generate.