[Mesa-dev] [PATCH v2 2/8] util/u_atomic: add p_atomic_xchg

Nicolai Hähnle nhaehnle at gmail.com
Fri Nov 3 20:09:11 UTC 2017


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

The closest to it in the old-style gcc builtins is __sync_lock_test_and_set,
however, that is only guaranteed to work with values 0 and 1 and only
provides an acquire barrier. I also don't know about other OSes, so we
provide a simple & stupid emulation via p_atomic_cmpxchg.
---
 src/util/u_atomic.h | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/src/util/u_atomic.h b/src/util/u_atomic.h
index 2a5bbae295b..c6d4bde3439 100644
--- a/src/util/u_atomic.h
+++ b/src/util/u_atomic.h
@@ -5,20 +5,21 @@
  * No copyright claimed on this file.
  *
  */
 
 #include "no_extern_c.h"
 
 #ifndef U_ATOMIC_H
 #define U_ATOMIC_H
 
 #include <stdbool.h>
+#include <stdint.h>
 
 /* Favor OS-provided implementations.
  *
  * Where no OS-provided implementation is available, fall back to
  * locally coded assembly, compiler intrinsic or ultimately a
  * mutex-based implementation.
  */
 #if defined(__sun)
 #define PIPE_ATOMIC_OS_SOLARIS
 #elif defined(_MSC_VER)
@@ -40,20 +41,22 @@
 
 /* The builtins with explicit memory model are available since GCC 4.7. */
 #define p_atomic_set(_v, _i) __atomic_store_n((_v), (_i), __ATOMIC_RELEASE)
 #define p_atomic_read(_v) __atomic_load_n((_v), __ATOMIC_ACQUIRE)
 #define p_atomic_dec_zero(v) (__atomic_sub_fetch((v), 1, __ATOMIC_ACQ_REL) == 0)
 #define p_atomic_inc(v) (void) __atomic_add_fetch((v), 1, __ATOMIC_ACQ_REL)
 #define p_atomic_dec(v) (void) __atomic_sub_fetch((v), 1, __ATOMIC_ACQ_REL)
 #define p_atomic_add(v, i) (void) __atomic_add_fetch((v), (i), __ATOMIC_ACQ_REL)
 #define p_atomic_inc_return(v) __atomic_add_fetch((v), 1, __ATOMIC_ACQ_REL)
 #define p_atomic_dec_return(v) __atomic_sub_fetch((v), 1, __ATOMIC_ACQ_REL)
+#define p_atomic_xchg(v, i) __atomic_exchange_n((v), (i), __ATOMIC_ACQ_REL)
+#define PIPE_NATIVE_ATOMIC_XCHG
 
 #else
 
 #define p_atomic_set(_v, _i) (*(_v) = (_i))
 #define p_atomic_read(_v) (*(_v))
 #define p_atomic_dec_zero(v) (__sync_sub_and_fetch((v), 1) == 0)
 #define p_atomic_inc(v) (void) __sync_add_and_fetch((v), 1)
 #define p_atomic_dec(v) (void) __sync_sub_and_fetch((v), 1)
 #define p_atomic_add(v, i) (void) __sync_add_and_fetch((v), (i))
 #define p_atomic_inc_return(v) __sync_add_and_fetch((v), 1)
@@ -213,13 +216,40 @@
    sizeof(*v) == sizeof(uint32_t) ? atomic_cas_32((uint32_t *)(v), (uint32_t)(old), (uint32_t)(_new)) : \
    sizeof(*v) == sizeof(uint64_t) ? atomic_cas_64((uint64_t *)(v), (uint64_t)(old), (uint64_t)(_new)) : \
                                     (assert(!"should not get here"), 0))
 
 #endif
 
 #ifndef PIPE_ATOMIC
 #error "No pipe_atomic implementation selected"
 #endif
 
-
+#ifndef PIPE_NATIVE_ATOMIC_XCHG
+static inline uint32_t p_atomic_xchg_32(uint32_t *v, uint32_t i)
+{
+   uint32_t actual = p_atomic_read(v);
+   uint32_t expected;
+   do {
+      expected = actual;
+      actual = p_atomic_cmpxchg(v, expected, i);
+   } while (expected != actual);
+   return actual;
+}
+
+static inline uint64_t p_atomic_xchg_64(uint64_t *v, uint64_t i)
+{
+   uint64_t actual = p_atomic_read(v);
+   uint64_t expected;
+   do {
+      expected = actual;
+      actual = p_atomic_cmpxchg(v, expected, i);
+   } while (expected != actual);
+   return actual;
+}
+
+#define p_atomic_xchg(v, i) ((__typeof(*(v))) \
+   sizeof(*(v)) == sizeof(uint32_t) ? p_atomic_xchg_32((uint32_t *)(v), (uint32_t)(i)) : \
+   sizeof(*(v)) == sizeof(uint64_t) ? p_atomic_xchg_64((uint64_t *)(v), (uint64_t)(i)) : \
+                                      (assert(!"should not get here"), 0))
+#endif
 
 #endif /* U_ATOMIC_H */
-- 
2.11.0



More information about the mesa-dev mailing list