]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Add compiler barriers to Atomic_MFence
authorVMware, Inc <>
Wed, 18 Sep 2013 03:10:58 +0000 (20:10 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 21 Sep 2013 22:55:50 +0000 (15:55 -0700)
The MFENCE instruction ensures that all loads and stores that
preceed it are "globally visible" before any load or store that
follow it.  However, we don't have a compiler barrier in
Atomic_MFence and so the compiler can move code and defeat this.

While this bug has probably been around for quite a while, it
only came up recently now that the AtomicEpilogue() is compiled
out.  That contains a compiler memory barrier, and while it's
not technically sufficient (need barrier before the MFENCE too),
it was apparently enough to discourage the code motion in
practice.

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/include/vm_atomic.h

index 31fc89354ee29e4fb57fdcc06fca88b1be48509d..36d9a6898dbacd4f4a6e263f783c2f2c917b175b 100644 (file)
@@ -90,9 +90,10 @@ long  _InterlockedCompareExchange(long volatile*, long, long);
 long  _InterlockedExchangeAdd(long volatile*, long);
 long  _InterlockedDecrement(long volatile*);
 long  _InterlockedIncrement(long volatile*);
+void  _ReadWriteBarrier(void);
 #pragma intrinsic(_InterlockedExchange, _InterlockedCompareExchange)
 #pragma intrinsic(_InterlockedExchangeAdd, _InterlockedDecrement)
-#pragma intrinsic(_InterlockedIncrement)
+#pragma intrinsic(_InterlockedIncrement, _ReadWriteBarrier)
 
 #if defined(VM_X86_64)
 long     _InterlockedAnd(long volatile*, long);
@@ -2771,6 +2772,16 @@ MAKE_ATOMIC_TYPE(Ptr, 32, void const *, void *, uintptr_t)
 MAKE_ATOMIC_TYPE(Int, 32, int, int, int)
 
 
+/* Prevent the compiler from re-ordering memory references. */
+#ifdef __GNUC__
+#define ATOMIC_COMPILER_BARRIER()   __asm__ __volatile__ ("": : :"memory")
+#elif defined(_MSC_VER)
+#define ATOMIC_COMPILER_BARRIER()   _ReadWriteBarrier()
+#else
+#error No compiler defined for ATOMIC_COMPILER_BARRIER
+#endif
+
+
 /*
  *-----------------------------------------------------------------------------
  *
@@ -2795,7 +2806,13 @@ static INLINE void
 Atomic_MFence(void)
 {
    Atomic_uint32 fence;
+   ATOMIC_COMPILER_BARRIER();
    Atomic_Xor(&fence, 0x1);
+   ATOMIC_COMPILER_BARRIER();
 }
 
+#ifdef ATOMIC_COMPILER_BARRIER
+#undef ATOMIC_COMPILER_BARRIER
+#endif
+
 #endif // ifndef _ATOMIC_H_