2009-03-16 10:40:18 +00:00
|
|
|
/**
|
|
|
|
* 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
|
|
|
|
|
2009-03-16 11:27:47 +00:00
|
|
|
#include "p_compiler.h"
|
2009-03-16 10:40:18 +00:00
|
|
|
#include "p_defines.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
|
2009-03-17 09:56:00 +00:00
|
|
|
p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
|
2009-03-16 10:40:18 +00:00
|
|
|
{
|
2009-03-17 09:56:00 +00:00
|
|
|
return __sync_val_compare_and_swap(&v->count, old, _new);
|
2009-03-16 10:40:18 +00:00
|
|
|
}
|
|
|
|
|
2009-03-17 09:54:08 +00:00
|
|
|
#elif (defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)) /* (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)
|
|
|
|
#define p_atomic_dec_zero(_v) ((boolean) --(_v)->count)
|
|
|
|
#define p_atomic_inc(_v) ((void) (_v)->count++)
|
|
|
|
#define p_atomic_dec(_v) ((void) (_v)->count--)
|
2009-03-17 09:56:00 +00:00
|
|
|
#define p_atomic_cmpxchg(_v, old, _new) ((_v)->count == old ? (_v)->count = (_new) : (_v)->count)
|
2009-03-17 09:54:08 +00:00
|
|
|
|
|
|
|
#elif (defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)) /* (defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)) */
|
2009-03-16 12:42:22 +00:00
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
int32_t *pcount = &v->count;
|
|
|
|
unsigned char c;
|
|
|
|
|
|
|
|
__asm {
|
|
|
|
mov eax, [pcount]
|
|
|
|
lock dec dword ptr [eax]
|
|
|
|
sete byte ptr [c]
|
|
|
|
}
|
|
|
|
|
|
|
|
return c != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE void
|
|
|
|
p_atomic_inc(struct pipe_atomic *v)
|
|
|
|
{
|
|
|
|
int32_t *pcount = &v->count;
|
|
|
|
|
|
|
|
__asm {
|
|
|
|
mov eax, [pcount]
|
|
|
|
lock inc dword ptr [eax]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE void
|
|
|
|
p_atomic_dec(struct pipe_atomic *v)
|
|
|
|
{
|
|
|
|
int32_t *pcount = &v->count;
|
|
|
|
|
|
|
|
__asm {
|
|
|
|
mov eax, [pcount]
|
|
|
|
lock dec dword ptr [eax]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE int32_t
|
2009-03-17 09:56:00 +00:00
|
|
|
p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
|
2009-03-16 12:42:22 +00:00
|
|
|
{
|
|
|
|
int32_t *pcount = &v->count;
|
|
|
|
int32_t orig;
|
|
|
|
|
|
|
|
__asm {
|
|
|
|
mov ecx, [pcount]
|
|
|
|
mov eax, [old]
|
2009-03-17 09:56:00 +00:00
|
|
|
mov edx, [_new]
|
2009-03-16 12:42:22 +00:00
|
|
|
lock cmpxchg [ecx], edx
|
|
|
|
mov [orig], eax
|
|
|
|
}
|
|
|
|
|
|
|
|
return orig;
|
|
|
|
}
|
|
|
|
|
|
|
|
#elif (defined(PIPE_SUBSYSTEM_WINDOWS_USER)) /* (defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)) */
|
2009-03-16 12:07:22 +00:00
|
|
|
|
|
|
|
struct pipe_atomic
|
|
|
|
{
|
|
|
|
long 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)
|
|
|
|
{
|
|
|
|
return InterlockedDecrement(&v->count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE void
|
|
|
|
p_atomic_inc(struct pipe_atomic *v)
|
|
|
|
{
|
|
|
|
InterlockedIncrement(&v->count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE void
|
|
|
|
p_atomic_dec(struct pipe_atomic *v)
|
|
|
|
{
|
|
|
|
InterlockedDecrement(&v->count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static INLINE int32_t
|
2009-03-17 09:56:00 +00:00
|
|
|
p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
|
2009-03-16 12:07:22 +00:00
|
|
|
{
|
2009-03-17 09:56:00 +00:00
|
|
|
return InterlockedCompareExchange(&v->count, _new, old);
|
2009-03-16 12:07:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#else /* (defined(PIPE_SUBSYSTEM_WINDOWS_USER)) */
|
2009-03-16 10:40:18 +00:00
|
|
|
|
|
|
|
#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)
|
|
|
|
{
|
2009-03-16 11:36:22 +00:00
|
|
|
pipe_mutex_init(v->mutex);
|
2009-03-16 10:40:18 +00:00
|
|
|
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
|
2009-03-17 09:56:00 +00:00
|
|
|
p_atomic_cmpxchg(struct pipe_atomic *v, int32_t old, int32_t _new)
|
2009-03-16 10:40:18 +00:00
|
|
|
{
|
|
|
|
int32_t ret;
|
|
|
|
|
|
|
|
pipe_mutex_lock(v->mutex);
|
|
|
|
ret = v->count;
|
|
|
|
if (ret == old)
|
2009-03-17 09:56:00 +00:00
|
|
|
v->count = _new;
|
2009-03-16 10:40:18 +00:00
|
|
|
pipe_mutex_unlock(v->mutex);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* (defined(PIPE_CC_GCC)) */
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#endif /* P_ATOMIC_H */
|