diff options
| author | Lennart Poettering <lennart@poettering.net> | 2007-09-04 21:25:26 +0000 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2007-09-04 21:25:26 +0000 | 
| commit | a4757a1dd90db5d6f1115205b452a232e4af58d3 (patch) | |
| tree | 728ea22de7eeb45630bfc03d9f0e3d620451a88c | |
| parent | 984ef82e52822abdf6492ed13b016b6b115414b4 (diff) | |
add native amd64 atomic int implementation
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1770 fefdeb5f-60dc-0310-8127-8f9354f1896f
| -rw-r--r-- | src/pulsecore/atomic.h | 87 | 
1 files changed, 83 insertions, 4 deletions
diff --git a/src/pulsecore/atomic.h b/src/pulsecore/atomic.h index b5c1ad9e..6e33c993 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 <config.h> +#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 */  | 
