Reviewed-by: Marek Olšák <marek.ol...@amd.com> Marek
On Fri, Nov 3, 2017 at 9:09 PM, Nicolai Hähnle <nhaeh...@gmail.com> wrote: > From: Nicolai Hähnle <nicolai.haeh...@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 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > https://lists.freedesktop.org/mailman/listinfo/mesa-dev _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev