+ /* All threads should read qparity before accessing data structure
+ * where new ptr points to.
+ */
+ /* Write new ptr before changing the qparity */
+ smp_mb();
+
+ /*
+ * Mark the writer thread offline to make sure we don't wait for
+ * our own quiescent state. This allows using synchronize_rcu() in
+ * threads registered as readers.
+ */
+ if (was_online)
+ STORE_SHARED(rcu_reader_qs_gp, 0);
+
+ internal_urcu_lock();
+
+ switch_next_urcu_qparity(); /* 0 -> 1 */
+
+ /*
+ * Must commit qparity update to memory before waiting for parity
+ * 0 quiescent state. Failure to do so could result in the writer
+ * waiting forever while new readers are always accessing data (no
+ * progress).
+ * Ensured by STORE_SHARED and LOAD_SHARED.
+ */
+
+ /*
+ * Wait for previous parity to be empty of readers.
+ */
+ wait_for_quiescent_state(); /* Wait readers in parity 0 */
+
+ /*
+ * Must finish waiting for quiescent state for parity 0 before
+ * committing qparity update to memory. Failure to do so could result in
+ * the writer waiting forever while new readers are always accessing
+ * data (no progress).
+ * Ensured by STORE_SHARED and LOAD_SHARED.
+ */
+
+ switch_next_urcu_qparity(); /* 1 -> 0 */
+
+ /*
+ * Must commit qparity update to memory before waiting for parity
+ * 1 quiescent state. Failure to do so could result in the writer
+ * waiting forever while new readers are always accessing data (no
+ * progress).
+ * Ensured by STORE_SHARED and LOAD_SHARED.
+ */
+
+ /*
+ * Wait for previous parity to be empty of readers.
+ */
+ wait_for_quiescent_state(); /* Wait readers in parity 1 */
+
+ internal_urcu_unlock();
+
+ /*
+ * Finish waiting for reader threads before letting the old ptr being
+ * freed.
+ */
+ if (was_online)
+ _STORE_SHARED(rcu_reader_qs_gp, LOAD_SHARED(urcu_gp_ctr));
+ smp_mb();
+}
+#else /* !(BITS_PER_LONG < 64) */
+void synchronize_rcu(void)
+{
+ unsigned long was_online;
+
+ was_online = rcu_reader_qs_gp;