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_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)) /* (defined(PIPE_CC_GCC)) */
76 #define p_atomic_set(_v, _i) ((_v)->count = (_i))
77 #define p_atomic_read(_v) ((_v)->count)
78 #define p_atomic_dec_zero(_v) ((boolean) --(_v)->count)
79 #define p_atomic_inc(_v) ((void) (_v)->count++)
80 #define p_atomic_dec(_v) ((void) (_v)->count--)
81 #define p_atomic_cmpxchg(_v, old, _new) ((_v)->count == old ? (_v)->count = (_new) : (_v)->count)
83 #elif (defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)) /* (defined(PIPE_SUBSYSTEM_WINDOWS_DISPLAY) || defined(PIPE_SUBSYSTEM_WINDOWS_MINIPORT)) */
90 #define p_atomic_set(_v, _i) ((_v)->count = (_i))
91 #define p_atomic_read(_v) ((_v)->count)
94 p_atomic_dec_zero(struct pipe_atomic
*v
)
96 int32_t *pcount
= &v
->count
;
101 lock dec dword ptr
[eax
]
109 p_atomic_inc(struct pipe_atomic
*v
)
111 int32_t *pcount
= &v
->count
;
115 lock inc dword ptr
[eax
]
120 p_atomic_dec(struct pipe_atomic
*v
)
122 int32_t *pcount
= &v
->count
;
126 lock dec dword ptr
[eax
]
130 static INLINE
int32_t
131 p_atomic_cmpxchg(struct pipe_atomic
*v
, int32_t old
, int32_t _new
)
133 int32_t *pcount
= &v
->count
;
140 lock cmpxchg
[ecx
], edx
147 #elif (defined(PIPE_SUBSYSTEM_WINDOWS_USER)) /* (defined(PIPE_ARCH_X86) && defined(PIPE_CC_MSVC)) */
154 #define p_atomic_set(_v, _i) ((_v)->count = (_i))
155 #define p_atomic_read(_v) ((_v)->count)
157 static INLINE boolean
158 p_atomic_dec_zero(struct pipe_atomic
*v
)
160 return InterlockedDecrement(&v
->count
);
164 p_atomic_inc(struct pipe_atomic
*v
)
166 InterlockedIncrement(&v
->count
);
170 p_atomic_dec(struct pipe_atomic
*v
)
172 InterlockedDecrement(&v
->count
);
175 static INLINE
int32_t
176 p_atomic_cmpxchg(struct pipe_atomic
*v
, int32_t old
, int32_t _new
)
178 return InterlockedCompareExchange(&v
->count
, _new
, old
);
181 #else /* (defined(PIPE_SUBSYSTEM_WINDOWS_USER)) */
183 #include "pipe/p_thread.h"
186 * This implementation should really not be used.
187 * Add an assembly port instead. It may abort and
188 * doesn't destroy used mutexes.
197 p_atomic_set(struct pipe_atomic
*v
, int32_t i
)
199 pipe_mutex_init(v
->mutex
);
200 pipe_mutex_lock(v
->mutex
);
202 pipe_mutex_unlock(v
->mutex
);
205 static INLINE
int32_t
206 p_atomic_read(struct pipe_atomic
*v
)
210 pipe_mutex_lock(v
->mutex
);
212 pipe_mutex_unlock(v
->mutex
);
217 p_atomic_inc(struct pipe_atomic
*v
)
219 pipe_mutex_lock(v
->mutex
);
221 pipe_mutex_unlock(v
->mutex
);
225 p_atomic_dec(struct pipe_atomic
*v
)
227 pipe_mutex_lock(v
->mutex
);
229 pipe_mutex_unlock(v
->mutex
);
232 static INLINE boolean
233 p_atomic_dec_zero(struct pipe_atomic
*v
)
237 pipe_mutex_lock(v
->mutex
);
238 ret
= (--v
->count
== 0);
239 pipe_mutex_unlock(v
->mutex
);
243 static INLINE
int32_t
244 p_atomic_cmpxchg(struct pipe_atomic
*v
, int32_t old
, int32_t _new
)
248 pipe_mutex_lock(v
->mutex
);
252 pipe_mutex_unlock(v
->mutex
);
257 #endif /* (defined(PIPE_CC_GCC)) */
263 #endif /* P_ATOMIC_H */