+/* Makes the calling thread block on the 'barrier' until all
+ * 'barrier->size' threads hit the barrier.
+ * ovs_barrier provides the necessary acquire-release semantics to make
+ * the effects of prior memory accesses of all the participating threads
+ * visible on return and to prevent the following memory accesses to be
+ * reordered before the ovs_barrier_block(). */
+void
+ovs_barrier_block(struct ovs_barrier *barrier)
+{
+ uint64_t seq = seq_read(barrier->seq);
+ uint32_t orig;
+
+ orig = atomic_count_inc(&barrier->count);
+ if (orig + 1 == barrier->size) {
+ atomic_count_set(&barrier->count, 0);
+ /* seq_change() serves as a release barrier against the other threads,
+ * so the zeroed count is visible to them as they continue. */
+ seq_change(barrier->seq);
+ } else {
+ /* To prevent thread from waking up by other event,
+ * keeps waiting for the change of 'barrier->seq'. */
+ while (seq == seq_read(barrier->seq)) {
+ seq_wait(barrier->seq, seq);
+ poll_block();
+ }
+ }