diff options
Diffstat (limited to 'src/gallium/include/pipe')
| -rw-r--r-- | src/gallium/include/pipe/p_atomic.h | 154 | 
1 files changed, 154 insertions, 0 deletions
diff --git a/src/gallium/include/pipe/p_atomic.h b/src/gallium/include/pipe/p_atomic.h new file mode 100644 index 0000000000..578d59480e --- /dev/null +++ b/src/gallium/include/pipe/p_atomic.h @@ -0,0 +1,154 @@ +/** + * Many similar implementations exist. See for example libwsbm + * or the linux kernel include/atomic.h + * + * No copyright claimed on this file. + * + */ + +#ifndef P_ATOMIC_H +#define P_ATOMIC_H + +#include "p_defines.h" +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if (defined(PIPE_CC_GCC)) +struct pipe_atomic { +   int32_t count; +}; + +#define p_atomic_set(_v, _i) ((_v)->count = (_i)) +#define p_atomic_read(_v) ((_v)->count) + + +static INLINE boolean +p_atomic_dec_zero(struct pipe_atomic *v) +{ +#ifdef __i386__ +   unsigned char c; + +   __asm__ __volatile__("lock; decl %0; sete %1":"+m"(v->count), "=qm"(c) +			::"memory"); + +   return c != 0; +#else  /* __i386__*/ +   return (__sync_sub_and_fetch(&v->count, 1) == 0); +#endif /* __i386__*/ +} + +static INLINE void +p_atomic_inc(struct pipe_atomic *v) +{ +#ifdef __i386__ +   __asm__ __volatile__("lock; incl %0":"+m"(v->count)); +#else /* __i386__*/ +   (void) __sync_add_and_fetch(&v->count, 1); +#endif /* __i386__*/ +} + +static INLINE void +p_atomic_dec(struct pipe_atomic *v) +{ +#ifdef __i386__ +   __asm__ __volatile__("lock; decl %0":"+m"(v->count)); +#else /* __i386__*/ +   (void) __sync_sub_and_fetch(&v->count, 1); +#endif /* __i386__*/ +} + +static INLINE int32_t +p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t new) +{ +   return __sync_val_compare_and_swap(&v->count, old, new); +} + +#else /* (defined(PIPE_CC_GCC)) */ + +#include "pipe/p_thread.h" + +/** + * This implementation should really not be used. + * Add an assembly port instead. It may abort and + * doesn't destroy used mutexes. + */ + +struct pipe_atomic { +   pipe_mutex mutex; +   int32_t count; +}; + +static INLINE void +p_atomic_set(struct pipe_atomic *v, int32_t i) +{ +   int ret; +   ret = pipe_mutex_init(v->mutex); +   if (ret) +      abort(); +   pipe_mutex_lock(v->mutex); +   v->count = i; +   pipe_mutex_unlock(v->mutex); +} + +static INLINE int32_t +p_atomic_read(struct pipe_atomic *v) +{ +   int32_t ret; + +   pipe_mutex_lock(v->mutex); +   ret = v->count; +   pipe_mutex_unlock(v->mutex); +   return ret; +} + +static INLINE void +p_atomic_inc(struct pipe_atomic *v) +{ +   pipe_mutex_lock(v->mutex); +   ++v->count; +   pipe_mutex_unlock(v->mutex); +} + +static INLINE void +p_atomic_dec(struct pipe_atomic *v) +{ +   pipe_mutex_lock(v->mutex); +   --v->count; +   pipe_mutex_unlock(v->mutex); +} + +static INLINE boolean +p_atomic_dec_zero(struct pipe_atomic *v) +{ +   boolean ret; + +   pipe_mutex_lock(v->mutex); +   ret = (--v->count == 0); +   pipe_mutex_unlock(v->mutex); +   return ret; +} + +static INLINE int32_t +p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t new) +{ +   int32_t ret; + +   pipe_mutex_lock(v->mutex); +   ret = v->count; +   if (ret == old) +      v->count = new; +   pipe_mutex_unlock(v->mutex); + +   return ret; +} + +#endif /* (defined(PIPE_CC_GCC)) */ + +#ifdef __cplusplus +} +#endif + +#endif /* P_ATOMIC_H */  | 
