]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Prohibit use of Atomic_Read64() and Atomic_Write64() on misaligned vars.
authorVMware, Inc <>
Thu, 18 Nov 2010 22:40:48 +0000 (14:40 -0800)
committerMarcelo Vanzin <mvanzin@vmware.com>
Thu, 18 Nov 2010 22:40:48 +0000 (14:40 -0800)
This is necessary since the functions do not provide any atomicity
guarantees in the misaligned case.

Add new functions, Atomic_ReadUnaligned64() and Atomic_WriteUnaligned64(),
and use these instead.

For the time being this change applies just to the VMM.

Signed-off-by: Marcelo Vanzin <mvanzin@vmware.com>
open-vm-tools/lib/include/vm_atomic.h

index dbaafd6875d151b59d165afc1a2a427fea13a881..a8615fa9f58c4027251d52ba1ff7f85f11d99c13 100644 (file)
@@ -1780,10 +1780,11 @@ Atomic_Read64(Atomic_uint64 const *var) // IN
 #elif defined(__GNUC__) && defined(__x86_64__)
    uint64 value;
 
+#ifdef VMM
+   ASSERT((uintptr_t)var % 8 == 0);
+#endif
    /*
-    * We have no evidence that suggests GCC will split this read into
-    * two move instructions.  However, we prefer to be defensive in
-    * light of errors seen in Atomic_Write64.
+    * Use asm to ensure we emit a single load.
     */
    __asm__ __volatile__(
       "movq %1, %0"
@@ -1838,6 +1839,35 @@ Atomic_Read64(Atomic_uint64 const *var) // IN
 }
 
 
+/*
+ *----------------------------------------------------------------------
+ *
+ * Atomic_ReadUnaligned64 --
+ *
+ *      Atomically read a 64 bit integer, possibly misaligned.
+ *      This function can be *very* expensive, costing over 50 kcycles
+ *      on Nehalem.
+ * 
+ *      Note that "var" needs to be writable, even though it will not
+ *      be modified.
+ *
+ * Results:
+ *      The value of the atomic variable.
+ *
+ * Side effects:
+ *      None
+ *
+ *----------------------------------------------------------------------
+ */
+#if defined(__x86_64__)
+static INLINE uint64
+Atomic_ReadUnaligned64(Atomic_uint64 const *var)
+{
+   return Atomic_ReadIfEqualWrite64((Atomic_uint64*)var, 0, 0);
+}
+#endif
+
+
 /*
  *----------------------------------------------------------------------
  *
@@ -2070,6 +2100,10 @@ Atomic_Write64(Atomic_uint64 *var, // IN
 {
 #if defined(__x86_64__)
 #if defined(__GNUC__)
+
+#ifdef VMM
+   ASSERT((uintptr_t)var % 8 == 0);
+#endif
    /*
     * There is no move instruction for 64-bit immediate to memory, so unless
     * the immediate value fits in 32-bit (i.e. can be sign-extended), GCC