bf445d
From: Paolo Bonzini <pbonzini@redhat.com>
bf445d
Date: Wed, 3 Jun 2015 14:21:20 +0200
bf445d
Subject: [PATCH] atomics: add explicit compiler fence in __atomic memory
bf445d
 barriers
bf445d
bf445d
__atomic_thread_fence does not include a compiler barrier; in the
bf445d
C++11 memory model, fences take effect in combination with other
bf445d
atomic operations.  GCC implements this by making __atomic_load and
bf445d
__atomic_store access memory as if the pointer was volatile, and
bf445d
leaves no trace whatsoever of acquire and release fences in the
bf445d
compiler's intermediate representation.
bf445d
bf445d
In QEMU, we want memory barriers to act on all memory, but at the same
bf445d
time we would like to use __atomic_thread_fence for portability reasons.
bf445d
Add compiler barriers manually around the __atomic_thread_fence.
bf445d
bf445d
Message-Id: <1433334080-14912-1-git-send-email-pbonzini@redhat.com>
bf445d
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
bf445d
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
bf445d
(cherry picked from commit 3bbf572345c65813f86a8fc434ea1b23beb08e16)
bf445d
---
bf445d
 include/qemu/atomic.h | 12 +++++++++---
bf445d
 1 file changed, 9 insertions(+), 3 deletions(-)
bf445d
bf445d
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
bf445d
index 98e05ca..bd2c075 100644
bf445d
--- a/include/qemu/atomic.h
bf445d
+++ b/include/qemu/atomic.h
bf445d
@@ -99,7 +99,13 @@
bf445d
 
bf445d
 #ifndef smp_wmb
bf445d
 #ifdef __ATOMIC_RELEASE
bf445d
-#define smp_wmb()   __atomic_thread_fence(__ATOMIC_RELEASE)
bf445d
+/* __atomic_thread_fence does not include a compiler barrier; instead,
bf445d
+ * the barrier is part of __atomic_load/__atomic_store's "volatile-like"
bf445d
+ * semantics. If smp_wmb() is a no-op, absence of the barrier means that
bf445d
+ * the compiler is free to reorder stores on each side of the barrier.
bf445d
+ * Add one here, and similarly in smp_rmb() and smp_read_barrier_depends().
bf445d
+ */
bf445d
+#define smp_wmb()   ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); barrier(); })
bf445d
 #else
bf445d
 #define smp_wmb()   __sync_synchronize()
bf445d
 #endif
bf445d
@@ -107,7 +113,7 @@
bf445d
 
bf445d
 #ifndef smp_rmb
bf445d
 #ifdef __ATOMIC_ACQUIRE
bf445d
-#define smp_rmb()   __atomic_thread_fence(__ATOMIC_ACQUIRE)
bf445d
+#define smp_rmb()   ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); barrier(); })
bf445d
 #else
bf445d
 #define smp_rmb()   __sync_synchronize()
bf445d
 #endif
bf445d
@@ -115,7 +121,7 @@
bf445d
 
bf445d
 #ifndef smp_read_barrier_depends
bf445d
 #ifdef __ATOMIC_CONSUME
bf445d
-#define smp_read_barrier_depends()   __atomic_thread_fence(__ATOMIC_CONSUME)
bf445d
+#define smp_read_barrier_depends()   ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); barrier(); })
bf445d
 #else
bf445d
 #define smp_read_barrier_depends()   barrier()
bf445d
 #endif