From 978f0ee2decad23e1a3923bcfeda7e0e33ac7c14 Mon Sep 17 00:00:00 2001
From: Jorge Aparicio <jorge@japaric.io>
Date: Wed, 8 Nov 2017 00:50:26 +0100
Subject: [PATCH] add a compiler barrier

---
 src/lib.rs              |  1 +
 src/ring_buffer/spsc.rs | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+)

diff --git a/src/lib.rs b/src/lib.rs
index d79b499..53e58ec 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -144,6 +144,7 @@
 //! is_send::<Vec<NotSend, [NotSend; 4]>>();
 //! ```
 
+#![cfg_attr(not(target_has_atomic = "ptr"), feature(asm))]
 #![cfg_attr(target_has_atomic = "ptr", feature(const_atomic_usize_new))]
 #![deny(missing_docs)]
 #![feature(cfg_target_has_atomic)]
diff --git a/src/ring_buffer/spsc.rs b/src/ring_buffer/spsc.rs
index 05e4435..6ea265f 100644
--- a/src/ring_buffer/spsc.rs
+++ b/src/ring_buffer/spsc.rs
@@ -6,6 +6,14 @@ use core::sync::atomic::Ordering;
 use BufferFullError;
 use ring_buffer::RingBuffer;
 
+// Compiler barrier
+#[cfg(not(target_has_atomic = "ptr"))]
+macro_rules! barrier {
+    () => {
+        unsafe { asm!("" ::: "memory") }
+    }
+}
+
 impl<T, A> RingBuffer<T, A>
 where
     A: Unsize<[T]>,
@@ -75,6 +83,12 @@ where
         // consumer so we inform this to the compiler using a volatile load
         if rb.head != unsafe { ptr::read_volatile(&rb.tail) } {
             let item = unsafe { ptr::read(buffer.get_unchecked(rb.head)) };
+
+            // NOTE(barrier!) this ensures that the compiler won't place the instructions to read
+            // the data *before* the instructions to increment the `head` pointer -- note that this
+            // won't be enough on architectures that allow out of order execution
+            barrier!();
+
             rb.head = (rb.head + 1) % n;
             Some(item)
         } else {
@@ -146,6 +160,10 @@ where
         if next_tail != unsafe { ptr::read_volatile(&rb.head) } {
             // NOTE(ptr::write) see the other `enqueue` implementation above for details
             unsafe { ptr::write(buffer.get_unchecked_mut(rb.tail), item) }
+
+            // NOTE(barrier!) see the NOTE(barrier!) above
+            barrier!();
+
             rb.tail = next_tail;
             Ok(())
         } else {
-- 
GitLab