From a4757a1dd90db5d6f1115205b452a232e4af58d3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 4 Sep 2007 21:25:26 +0000 Subject: [PATCH] add native amd64 atomic int implementation git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1770 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/pulsecore/atomic.h | 87 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 83 insertions(+), 4 deletions(-) diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index b5c1ad9..6e33c99 100644 --- a/src/pulsecore/atomic.h +++ b/src/pulsecore/atomic.h @@ -37,9 +37,14 @@ * libatomic_ops */ -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)) +/* We have to include config.h here, which sucks */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_ATOMIC_BUILTINS -/* gcc based implementation */ +/* __sync based implementation */ typedef struct pa_atomic { volatile int value; @@ -83,7 +88,7 @@ static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { } typedef struct pa_atomic_ptr { - volatile long value; + volatile unsigned long value; } pa_atomic_ptr_t; #define PA_ATOMIC_PTR_INIT(v) { .value = (long) (v) } @@ -94,7 +99,7 @@ static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { } static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { - a->value = (long) p; + a->value = (unsigned long) p; __sync_synchronize(); } @@ -102,6 +107,80 @@ static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* n return __sync_bool_compare_and_swap(&a->value, (long) old_p, (long) new_p); } +#elif defined(__GNUC__) && (defined(__amd64__) || defined(__x86_64__)) + +/* Addapted from glibc */ + +typedef struct pa_atomic { + volatile int value; +} pa_atomic_t; + +#define PA_ATOMIC_INIT(v) { .value = (v) } + +static inline int pa_atomic_load(const pa_atomic_t *a) { + return a->value; +} + +static inline void pa_atomic_store(pa_atomic_t *a, int i) { + a->value = i; +} + +static inline int pa_atomic_add(pa_atomic_t *a, int i) { + int result; + + __asm __volatile ("lock; xaddl %0, %1" + : "=r" (result), "=m" (a->value) + : "0" (i), "m" (a->value)); + + return result; +} + +static inline int pa_atomic_sub(pa_atomic_t *a, int i) { + return pa_atomic_add(a, -i); +} + +static inline int pa_atomic_inc(pa_atomic_t *a) { + return pa_atomic_add(a, 1); +} + +static inline int pa_atomic_dec(pa_atomic_t *a) { + return pa_atomic_sub(a, 1); +} + +static inline int pa_atomic_cmpxchg(pa_atomic_t *a, int old_i, int new_i) { + int result; + + __asm__ __volatile__ ("lock; cmpxchgl %2, %1" + : "=a" (result), "=m" (a->value) + : "r" (new_i), "m" (a->value), "0" (old_i)); + + return result == oldval; +} + +typedef struct pa_atomic_ptr { + volatile unsigned long value; +} pa_atomic_ptr_t; + +#define PA_ATOMIC_PTR_INIT(v) { .value = (long) (v) } + +static inline void* pa_atomic_ptr_load(const pa_atomic_ptr_t *a) { + return (void*) a->value; +} + +static inline void pa_atomic_ptr_store(pa_atomic_ptr_t *a, void *p) { + a->value = (unsigned long) p; +} + +static inline int pa_atomic_ptr_cmpxchg(pa_atomic_ptr_t *a, void *old_p, void* new_p) { + void *result; + + __asm__ __volatile__ ("lock; cmpxchgq %q2, %1" + : "=a" (result), "=m" (a->value) + : "r" (new_p), "m" (a->value), "0" (old_p)); + + return result; +} + #else /* libatomic_ops based implementation */ -- 2.7.4