2 * Many similar implementations exist. See for example libwsbm
3 * or the linux kernel include/atomic.h
5 * No copyright claimed on this file.
12 #include "p_compiler.h"
13 #include "p_defines.h"
19 #if (defined(PIPE_CC_GCC))
24 #define p_atomic_set(_v, _i) ((_v)->count = (_i))
25 #define p_atomic_read(_v) ((_v)->count)
29 p_atomic_dec_zero(struct pipe_atomic
*v
)
34 __asm__
__volatile__("lock; decl %0; sete %1":"+m"(v
->count
), "=qm"(c
)
39 return (__sync_sub_and_fetch(&v
->count
, 1) == 0);
44 p_atomic_inc(struct pipe_atomic
*v
)
47 __asm__
__volatile__("lock; incl %0":"+m"(v
->count
));
49 (void) __sync_add_and_fetch(&v
->count
, 1);
54 p_atomic_dec(struct pipe_atomic
*v
)
57 __asm__
__volatile__("lock; decl %0":"+m"(v
->count
));
59 (void) __sync_sub_and_fetch(&v
->count
, 1);
64 p_atomic_cmpxchg(struct pipe_atomic
*v
, int32_t old
, int32_t new)
66 return __sync_val_compare_and_swap(&v
->count
, old
, new);
69 #elif (defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)) /* (defined(PIPE_CC_GCC)) */
76 #define p_atomic_set(_v, _i) ((_v)->count = (_i))
77 #define p_atomic_read(_v) ((_v)->count)
80 p_atomic_dec_zero(struct pipe_atomic
*v
)
82 int32_t *pcount
= &v
->count
;
87 lock dec dword ptr
[eax
]
95 p_atomic_inc(struct pipe_atomic
*v
)
97 int32_t *pcount
= &v
->count
;
101 lock inc dword ptr
[eax
]
106 p_atomic_dec(struct pipe_atomic
*v
)
108 int32_t *pcount
= &v
->count
;
112 lock dec dword ptr
[eax
]
116 static INLINE
int32_t
117 p_atomic_cmpxchg(struct pipe_atomic
*v
, int32_t old
, int32_t new)
119 int32_t *pcount
= &v
->count
;
126 lock cmpxchg
[ecx
], edx
133 #elif (defined(PIPE_SUBSYSTEM_WINDOWS_USER)) /* (defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)) */
140 #define p_atomic_set(_v, _i) ((_v)->count = (_i))
141 #define p_atomic_read(_v) ((_v)->count)
143 static INLINE boolean
144 p_atomic_dec_zero(struct pipe_atomic
*v
)
146 return InterlockedDecrement(&v
->count
);
150 p_atomic_inc(struct pipe_atomic
*v
)
152 InterlockedIncrement(&v
->count
);
156 p_atomic_dec(struct pipe_atomic
*v
)
158 InterlockedDecrement(&v
->count
);
161 static INLINE
int32_t
162 p_atomic_cmpxchg(struct pipe_atomic
*v
, int32_t old
, int32_t new)
164 return InterlockedCompareExchange(&v
->count
, new, old
);
167 #else /* (defined(PIPE_SUBSYSTEM_WINDOWS_USER)) */
169 #include "pipe/p_thread.h"
172 * This implementation should really not be used.
173 * Add an assembly port instead. It may abort and
174 * doesn't destroy used mutexes.
183 p_atomic_set(struct pipe_atomic
*v
, int32_t i
)
185 pipe_mutex_init(v
->mutex
);
186 pipe_mutex_lock(v
->mutex
);
188 pipe_mutex_unlock(v
->mutex
);
191 static INLINE
int32_t
192 p_atomic_read(struct pipe_atomic
*v
)
196 pipe_mutex_lock(v
->mutex
);
198 pipe_mutex_unlock(v
->mutex
);
203 p_atomic_inc(struct pipe_atomic
*v
)
205 pipe_mutex_lock(v
->mutex
);
207 pipe_mutex_unlock(v
->mutex
);
211 p_atomic_dec(struct pipe_atomic
*v
)
213 pipe_mutex_lock(v
->mutex
);
215 pipe_mutex_unlock(v
->mutex
);
218 static INLINE boolean
219 p_atomic_dec_zero(struct pipe_atomic
*v
)
223 pipe_mutex_lock(v
->mutex
);
224 ret
= (--v
->count
== 0);
225 pipe_mutex_unlock(v
->mutex
);
229 static INLINE
int32_t
230 p_atomic_cmpxchg(struct pipe_atomic
*v
, int32_t old
, int32_t new)
234 pipe_mutex_lock(v
->mutex
);
238 pipe_mutex_unlock(v
->mutex
);
243 #endif /* (defined(PIPE_CC_GCC)) */
249 #endif /* P_ATOMIC_H */