yeahuh / rpms / qemu-kvm

Forked from rpms/qemu-kvm 2 years ago
Clone
9ae3a8
From d37475eb567b61ce6a18f9fcbf35eb929be8d99f Mon Sep 17 00:00:00 2001
9ae3a8
From: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Date: Fri, 19 Jun 2015 10:45:29 +0200
9ae3a8
Subject: [PATCH] atomics: add explicit compiler fence in __atomic memory
9ae3a8
 barriers
9ae3a8
9ae3a8
Message-id: <1434710730-26183-1-git-send-email-pbonzini@redhat.com>
9ae3a8
Patchwork-id: 66333
9ae3a8
O-Subject: [RHEL7.2/7.1.z qemu-kvm PATCH] atomics: add explicit compiler fence in __atomic memory barriers
9ae3a8
Bugzilla: 1142857
9ae3a8
RH-Acked-by: Fam Zheng <famz@redhat.com>
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
9ae3a8
9ae3a8
Bugzilla: 1142857 (aka 8*10^6/7)
9ae3a8
9ae3a8
Brew build: 9393725
9ae3a8
9ae3a8
__atomic_thread_fence does not include a compiler barrier; in the
9ae3a8
C++11 memory model, fences take effect in combination with other
9ae3a8
atomic operations.  GCC implements this by making __atomic_load and
9ae3a8
__atomic_store access memory as if the pointer was volatile, and
9ae3a8
leaves no trace whatsoever of acquire and release fences in the
9ae3a8
compiler's intermediate representation.
9ae3a8
9ae3a8
In QEMU, we want memory barriers to act on all memory, but at the same
9ae3a8
time we would like to use __atomic_thread_fence for portability reasons.
9ae3a8
Add compiler barriers manually around the __atomic_thread_fence.
9ae3a8
9ae3a8
Thanks to Uli and Kevin for analyzing this bug!
9ae3a8
9ae3a8
Message-Id: <1433334080-14912-1-git-send-email-pbonzini@redhat.com>
9ae3a8
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
(cherry picked from commit 3bbf572345c65813f86a8fc434ea1b23beb08e16)
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 include/qemu/atomic.h | 12 +++++++++---
9ae3a8
 1 file changed, 9 insertions(+), 3 deletions(-)
9ae3a8
9ae3a8
diff --git a/include/qemu/atomic.h b/include/qemu/atomic.h
9ae3a8
index 0aa8913..690d0d6 100644
9ae3a8
--- a/include/qemu/atomic.h
9ae3a8
+++ b/include/qemu/atomic.h
9ae3a8
@@ -99,7 +99,13 @@
9ae3a8
 
9ae3a8
 #ifndef smp_wmb
9ae3a8
 #ifdef __ATOMIC_RELEASE
9ae3a8
-#define smp_wmb()   __atomic_thread_fence(__ATOMIC_RELEASE)
9ae3a8
+/* __atomic_thread_fence does not include a compiler barrier; instead,
9ae3a8
+ * the barrier is part of __atomic_load/__atomic_store's "volatile-like"
9ae3a8
+ * semantics. If smp_wmb() is a no-op, absence of the barrier means that
9ae3a8
+ * the compiler is free to reorder stores on each side of the barrier.
9ae3a8
+ * Add one here, and similarly in smp_rmb() and smp_read_barrier_depends().
9ae3a8
+ */
9ae3a8
+#define smp_wmb()   ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); barrier(); })
9ae3a8
 #else
9ae3a8
 #define smp_wmb()   __sync_synchronize()
9ae3a8
 #endif
9ae3a8
@@ -107,7 +113,7 @@
9ae3a8
 
9ae3a8
 #ifndef smp_rmb
9ae3a8
 #ifdef __ATOMIC_ACQUIRE
9ae3a8
-#define smp_rmb()   __atomic_thread_fence(__ATOMIC_ACQUIRE)
9ae3a8
+#define smp_rmb()   ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); barrier(); })
9ae3a8
 #else
9ae3a8
 #define smp_rmb()   __sync_synchronize()
9ae3a8
 #endif
9ae3a8
@@ -115,7 +121,7 @@
9ae3a8
 
9ae3a8
 #ifndef smp_read_barrier_depends
9ae3a8
 #ifdef __ATOMIC_CONSUME
9ae3a8
-#define smp_read_barrier_depends()   __atomic_thread_fence(__ATOMIC_CONSUME)
9ae3a8
+#define smp_read_barrier_depends()   ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); barrier(); })
9ae3a8
 #else
9ae3a8
 #define smp_read_barrier_depends()   barrier()
9ae3a8
 #endif
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8