+ /*
+ * Move all waiters into our local queue.
+ */
+ urcu_move_waiters(&waiters, &gp_waiters);
+
+ if (cds_list_empty(®istry))
+ goto out;
+
+ /* Increment current G.P. */
+ CMM_STORE_SHARED(rcu_gp.ctr, rcu_gp.ctr + RCU_GP_CTR);
+
+ /*
+ * Must commit rcu_gp.ctr update to memory before waiting for
+ * quiescent state. Failure to do so could result in the writer
+ * waiting forever while new readers are always accessing data
+ * (no progress). Enforce compiler-order of store to rcu_gp.ctr
+ * before load URCU_TLS(rcu_reader).ctr.
+ */
+ cmm_barrier();
+
+ /*
+ * Adding a cmm_smp_mb() which is _not_ formally required, but makes the
+ * model easier to understand. It does not have a big performance impact
+ * anyway, given this is the write-side.
+ */
+ cmm_smp_mb();
+
+ /*
+ * Wait for readers to observe new count of be quiescent.
+ */
+ wait_for_readers(®istry, NULL, &qsreaders);
+
+ /*
+ * Put quiescent reader list back into registry.
+ */
+ cds_list_splice(&qsreaders, ®istry);
+out:
+ mutex_unlock(&rcu_gp_lock);
+ urcu_wake_all_waiters(&waiters);
+gp_end: