]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
atomic: add TestSetBitVector and TestClearBitVector functions
authorOliver Kurth <okurth@vmware.com>
Wed, 7 Feb 2018 00:32:37 +0000 (16:32 -0800)
committerOliver Kurth <okurth@vmware.com>
Wed, 7 Feb 2018 00:32:37 +0000 (16:32 -0800)
Implement atomic set/clear bit from a byte array.

Also add missing "memory" constraint to non-atomic ClearBitVector()
and ComplementBitVector().

open-vm-tools/lib/include/vm_atomic.h
open-vm-tools/lib/include/vm_basic_asm.h

index 049213f3eb9f111842fe84a7acbe8ce0daba2a0a..8edfe5c8405927f044f8fb81a3e948d1eb1dc9d1 100644 (file)
@@ -1,5 +1,5 @@
 /*********************************************************
- * Copyright (C) 1998-2017 VMware, Inc. All rights reserved.
+ * Copyright (C) 1998-2018 VMware, Inc. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as published
@@ -3844,6 +3844,91 @@ MAKE_ATOMIC_TYPE(Ptr, 32, void const *, void *, uintptr_t)
 MAKE_ATOMIC_TYPE(Int, 32, int, int, int)
 MAKE_ATOMIC_TYPE(Bool, 8, Bool, Bool, Bool)
 
+/*
+ * Define arbitrary sized bit vector to be used by
+ * Atomic_TestSetBitVector and Atomic_TestClearBitVector.
+ */
+#define ATOMIC_BITVECTOR(varName, capacity) \
+      Atomic_uint8 varName[CEILING(capacity, 8)]
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_TestSetBitVector --
+ *
+ *      Atomically test and set the bit 'index' in bit vector var.
+ *
+ *      The index input value specifies which bit to modify and is 0-based.
+ *
+ * Results:
+ *      Returns the value of the bit before modification.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+Atomic_TestSetBitVector(Atomic_uint8 *var, // IN/OUT
+                        unsigned index)    // IN
+{
+#if defined __x86_64__ && defined __GNUC__
+   Bool bit;
+   __asm__ __volatile__(
+      "lock; bts %2, %1;"
+      "setc %0"
+      : "=qQm" (bit), "+m" (var->value)
+      : "rI" (index)
+      : "cc", "memory"
+   );
+   return bit;
+#else
+   uint8 bit = 1 << index % 8;
+   return (Atomic_ReadOr8(var + index / 8, bit) & bit) != 0;
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Atomic_TestClearBitVector --
+ *
+ *      Atomically test and clear the bit 'index' in bit vector var.
+ *
+ *      The index input value specifies which bit to modify and is 0-based.
+ *
+ * Results:
+ *      Returns the value of the bit before modification.
+ *
+ * Side effects:
+ *      None
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static INLINE Bool
+Atomic_TestClearBitVector(Atomic_uint8 *var, // IN/OUT
+                          unsigned index)    // IN
+{
+#if defined __x86_64__ && defined __GNUC__
+   Bool bit;
+   __asm__ __volatile__(
+      "lock; btr %2, %1;"
+      "setc %0"
+      : "=qQm" (bit), "+m" (var->value)
+      : "rI" (index)
+      : "cc", "memory"
+   );
+   return bit;
+#else
+   uint8 bit = 1 << index % 8;
+   return (Atomic_ReadAnd8(var + index / 8, ~bit) & bit) != 0;
+#endif
+}
+
+
 #ifdef VM_ARM_64
 #   include "vm_atomic_arm64_end.h"
 #endif
index 751193721ed1a5c85b0d1730903cfe2dda38d4b6..e667b0b21b514db6d4a6386eed83276e7554083a 100644 (file)
@@ -1070,7 +1070,7 @@ ClearBitVector(void *var, int32 index)
       "setc %0"
       : "=qQm" (bit), "+m" (*(uint32 *)var)
       : "rI" (index)
-      : "cc"
+      : "memory", "cc"
    );
    return bit;
 #elif defined(_MSC_VER)
@@ -1092,7 +1092,7 @@ ComplementBitVector(void *var, int32 index)
       "setc %0"
       : "=qQm" (bit), "+m" (*(uint32 *)var)
       : "rI" (index)
-      : "cc"
+      : "memory", "cc"
    );
    return bit;
 #elif defined(_MSC_VER)