xref: /aosp_15_r20/external/virglrenderer/src/mesa/util/u_atomic.h (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
1*bbecb9d1SAndroid Build Coastguard Worker /**
2*bbecb9d1SAndroid Build Coastguard Worker  * Many similar implementations exist. See for example libwsbm
3*bbecb9d1SAndroid Build Coastguard Worker  * or the linux kernel include/atomic.h
4*bbecb9d1SAndroid Build Coastguard Worker  *
5*bbecb9d1SAndroid Build Coastguard Worker  * No copyright claimed on this file.
6*bbecb9d1SAndroid Build Coastguard Worker  *
7*bbecb9d1SAndroid Build Coastguard Worker  */
8*bbecb9d1SAndroid Build Coastguard Worker 
9*bbecb9d1SAndroid Build Coastguard Worker #include "no_extern_c.h"
10*bbecb9d1SAndroid Build Coastguard Worker 
11*bbecb9d1SAndroid Build Coastguard Worker #ifndef U_ATOMIC_H
12*bbecb9d1SAndroid Build Coastguard Worker #define U_ATOMIC_H
13*bbecb9d1SAndroid Build Coastguard Worker 
14*bbecb9d1SAndroid Build Coastguard Worker #include <stdbool.h>
15*bbecb9d1SAndroid Build Coastguard Worker #include <stdint.h>
16*bbecb9d1SAndroid Build Coastguard Worker 
17*bbecb9d1SAndroid Build Coastguard Worker /* Favor OS-provided implementations.
18*bbecb9d1SAndroid Build Coastguard Worker  *
19*bbecb9d1SAndroid Build Coastguard Worker  * Where no OS-provided implementation is available, fall back to
20*bbecb9d1SAndroid Build Coastguard Worker  * locally coded assembly, compiler intrinsic or ultimately a
21*bbecb9d1SAndroid Build Coastguard Worker  * mutex-based implementation.
22*bbecb9d1SAndroid Build Coastguard Worker  */
23*bbecb9d1SAndroid Build Coastguard Worker #if defined(__sun)
24*bbecb9d1SAndroid Build Coastguard Worker #define PIPE_ATOMIC_OS_SOLARIS
25*bbecb9d1SAndroid Build Coastguard Worker #elif defined(_MSC_VER)
26*bbecb9d1SAndroid Build Coastguard Worker #define PIPE_ATOMIC_MSVC_INTRINSIC
27*bbecb9d1SAndroid Build Coastguard Worker #elif defined(__GNUC__)
28*bbecb9d1SAndroid Build Coastguard Worker #define PIPE_ATOMIC_GCC_INTRINSIC
29*bbecb9d1SAndroid Build Coastguard Worker #else
30*bbecb9d1SAndroid Build Coastguard Worker #error "Unsupported platform"
31*bbecb9d1SAndroid Build Coastguard Worker #endif
32*bbecb9d1SAndroid Build Coastguard Worker 
33*bbecb9d1SAndroid Build Coastguard Worker 
34*bbecb9d1SAndroid Build Coastguard Worker /* Implementation using GCC-provided synchronization intrinsics
35*bbecb9d1SAndroid Build Coastguard Worker  */
36*bbecb9d1SAndroid Build Coastguard Worker #if defined(PIPE_ATOMIC_GCC_INTRINSIC)
37*bbecb9d1SAndroid Build Coastguard Worker 
38*bbecb9d1SAndroid Build Coastguard Worker #define PIPE_ATOMIC "GCC Sync Intrinsics"
39*bbecb9d1SAndroid Build Coastguard Worker 
40*bbecb9d1SAndroid Build Coastguard Worker #if defined(USE_GCC_ATOMIC_BUILTINS)
41*bbecb9d1SAndroid Build Coastguard Worker 
42*bbecb9d1SAndroid Build Coastguard Worker /* The builtins with explicit memory model are available since GCC 4.7. */
43*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_set(_v, _i) __atomic_store_n((_v), (_i), __ATOMIC_RELEASE)
44*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read(_v) __atomic_load_n((_v), __ATOMIC_ACQUIRE)
45*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read_relaxed(_v) __atomic_load_n((_v), __ATOMIC_RELAXED)
46*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_zero(v) (__atomic_sub_fetch((v), 1, __ATOMIC_ACQ_REL) == 0)
47*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc(v) (void) __atomic_add_fetch((v), 1, __ATOMIC_ACQ_REL)
48*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec(v) (void) __atomic_sub_fetch((v), 1, __ATOMIC_ACQ_REL)
49*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add(v, i) (void) __atomic_add_fetch((v), (i), __ATOMIC_ACQ_REL)
50*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc_return(v) __atomic_add_fetch((v), 1, __ATOMIC_ACQ_REL)
51*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_return(v) __atomic_sub_fetch((v), 1, __ATOMIC_ACQ_REL)
52*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add_return(v, i) __atomic_add_fetch((v), (i), __ATOMIC_ACQ_REL)
53*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_xchg(v, i) __atomic_exchange_n((v), (i), __ATOMIC_ACQ_REL)
54*bbecb9d1SAndroid Build Coastguard Worker #define PIPE_NATIVE_ATOMIC_XCHG
55*bbecb9d1SAndroid Build Coastguard Worker 
56*bbecb9d1SAndroid Build Coastguard Worker #else
57*bbecb9d1SAndroid Build Coastguard Worker 
58*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_set(_v, _i) (*(_v) = (_i))
59*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read(_v) (*(_v))
60*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read_relaxed(_v) (*(_v))
61*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_zero(v) (__sync_sub_and_fetch((v), 1) == 0)
62*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc(v) (void) __sync_add_and_fetch((v), 1)
63*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec(v) (void) __sync_sub_and_fetch((v), 1)
64*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add(v, i) (void) __sync_add_and_fetch((v), (i))
65*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc_return(v) __sync_add_and_fetch((v), 1)
66*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_return(v) __sync_sub_and_fetch((v), 1)
67*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add_return(v, i) __sync_add_and_fetch((v), (i))
68*bbecb9d1SAndroid Build Coastguard Worker 
69*bbecb9d1SAndroid Build Coastguard Worker #endif
70*bbecb9d1SAndroid Build Coastguard Worker 
71*bbecb9d1SAndroid Build Coastguard Worker /* There is no __atomic_* compare and exchange that returns the current value.
72*bbecb9d1SAndroid Build Coastguard Worker  * Also, GCC 5.4 seems unable to optimize a compound statement expression that
73*bbecb9d1SAndroid Build Coastguard Worker  * uses an additional stack variable with __atomic_compare_exchange[_n].
74*bbecb9d1SAndroid Build Coastguard Worker  */
75*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_cmpxchg(v, old, _new) \
76*bbecb9d1SAndroid Build Coastguard Worker    __sync_val_compare_and_swap((v), (old), (_new))
77*bbecb9d1SAndroid Build Coastguard Worker 
78*bbecb9d1SAndroid Build Coastguard Worker #endif
79*bbecb9d1SAndroid Build Coastguard Worker 
80*bbecb9d1SAndroid Build Coastguard Worker 
81*bbecb9d1SAndroid Build Coastguard Worker 
82*bbecb9d1SAndroid Build Coastguard Worker /* Unlocked version for single threaded environments, such as some
83*bbecb9d1SAndroid Build Coastguard Worker  * windows kernel modules.
84*bbecb9d1SAndroid Build Coastguard Worker  */
85*bbecb9d1SAndroid Build Coastguard Worker #if defined(PIPE_ATOMIC_OS_UNLOCKED)
86*bbecb9d1SAndroid Build Coastguard Worker 
87*bbecb9d1SAndroid Build Coastguard Worker #define PIPE_ATOMIC "Unlocked"
88*bbecb9d1SAndroid Build Coastguard Worker 
89*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_set(_v, _i) (*(_v) = (_i))
90*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read(_v) (*(_v))
91*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read_relaxed(_v) (*(_v))
92*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_zero(_v) (p_atomic_dec_return(_v) == 0)
93*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc(_v) ((void) p_atomic_inc_return(_v))
94*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec(_v) ((void) p_atomic_dec_return(_v))
95*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add(_v, _i) ((void) p_atomic_add_return((_v), (_i)))
96*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc_return(_v) (++(*(_v)))
97*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_return(_v) (--(*(_v)))
98*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add_return(_v, _i) (*(_v) = *(_v) + (_i))
99*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_cmpxchg(_v, _old, _new) (*(_v) == (_old) ? (*(_v) = (_new), (_old)) : *(_v))
100*bbecb9d1SAndroid Build Coastguard Worker 
101*bbecb9d1SAndroid Build Coastguard Worker #endif
102*bbecb9d1SAndroid Build Coastguard Worker 
103*bbecb9d1SAndroid Build Coastguard Worker 
104*bbecb9d1SAndroid Build Coastguard Worker #if defined(PIPE_ATOMIC_MSVC_INTRINSIC)
105*bbecb9d1SAndroid Build Coastguard Worker 
106*bbecb9d1SAndroid Build Coastguard Worker #define PIPE_ATOMIC "MSVC Intrinsics"
107*bbecb9d1SAndroid Build Coastguard Worker 
108*bbecb9d1SAndroid Build Coastguard Worker /* We use the Windows header's Interlocked*64 functions instead of the
109*bbecb9d1SAndroid Build Coastguard Worker  * _Interlocked*64 intrinsics wherever we can, as support for the latter varies
110*bbecb9d1SAndroid Build Coastguard Worker  * with target CPU, whereas Windows headers take care of all portability
111*bbecb9d1SAndroid Build Coastguard Worker  * issues: using intrinsics where available, falling back to library
112*bbecb9d1SAndroid Build Coastguard Worker  * implementations where not.
113*bbecb9d1SAndroid Build Coastguard Worker  */
114*bbecb9d1SAndroid Build Coastguard Worker #ifndef WIN32_LEAN_AND_MEAN
115*bbecb9d1SAndroid Build Coastguard Worker #define WIN32_LEAN_AND_MEAN 1
116*bbecb9d1SAndroid Build Coastguard Worker #endif
117*bbecb9d1SAndroid Build Coastguard Worker #include <windows.h>
118*bbecb9d1SAndroid Build Coastguard Worker #include <intrin.h>
119*bbecb9d1SAndroid Build Coastguard Worker #include <assert.h>
120*bbecb9d1SAndroid Build Coastguard Worker 
121*bbecb9d1SAndroid Build Coastguard Worker /* MSVC supports decltype keyword, but it's only supported on C++ and doesn't
122*bbecb9d1SAndroid Build Coastguard Worker  * quite work here; and if a C++-only solution is worthwhile, then it would be
123*bbecb9d1SAndroid Build Coastguard Worker  * better to use templates / function overloading, instead of decltype magic.
124*bbecb9d1SAndroid Build Coastguard Worker  * Therefore, we rely on implicit casting to LONGLONG for the functions that return
125*bbecb9d1SAndroid Build Coastguard Worker  */
126*bbecb9d1SAndroid Build Coastguard Worker 
127*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_set(_v, _i) (*(_v) = (_i))
128*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read(_v) (*(_v))
129*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read_relaxed(_v) (*(_v))
130*bbecb9d1SAndroid Build Coastguard Worker 
131*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_zero(_v) \
132*bbecb9d1SAndroid Build Coastguard Worker    (p_atomic_dec_return(_v) == 0)
133*bbecb9d1SAndroid Build Coastguard Worker 
134*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc(_v) \
135*bbecb9d1SAndroid Build Coastguard Worker    ((void) p_atomic_inc_return(_v))
136*bbecb9d1SAndroid Build Coastguard Worker 
137*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc_return(_v) (\
138*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(short)   ? _InterlockedIncrement16((short *)  (_v)) : \
139*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(long)    ? _InterlockedIncrement  ((long *)   (_v)) : \
140*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(__int64) ? InterlockedIncrement64 ((__int64 *)(_v)) : \
141*bbecb9d1SAndroid Build Coastguard Worker                                      (assert(!"should not get here"), 0))
142*bbecb9d1SAndroid Build Coastguard Worker 
143*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec(_v) \
144*bbecb9d1SAndroid Build Coastguard Worker    ((void) p_atomic_dec_return(_v))
145*bbecb9d1SAndroid Build Coastguard Worker 
146*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_return(_v) (\
147*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(short)   ? _InterlockedDecrement16((short *)  (_v)) : \
148*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(long)    ? _InterlockedDecrement  ((long *)   (_v)) : \
149*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(__int64) ? InterlockedDecrement64 ((__int64 *)(_v)) : \
150*bbecb9d1SAndroid Build Coastguard Worker                                      (assert(!"should not get here"), 0))
151*bbecb9d1SAndroid Build Coastguard Worker 
152*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add(_v, _i) \
153*bbecb9d1SAndroid Build Coastguard Worker    ((void) p_atomic_add_return((_v), (_i)))
154*bbecb9d1SAndroid Build Coastguard Worker 
155*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add_return(_v, _i) (\
156*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(char)    ? _InterlockedExchangeAdd8 ((char *)   (_v), (_i)) : \
157*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(short)   ? _InterlockedExchangeAdd16((short *)  (_v), (_i)) : \
158*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(long)    ? _InterlockedExchangeAdd  ((long *)   (_v), (_i)) : \
159*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(__int64) ? InterlockedExchangeAdd64((__int64 *)(_v), (_i)) : \
160*bbecb9d1SAndroid Build Coastguard Worker                                      (assert(!"should not get here"), 0))
161*bbecb9d1SAndroid Build Coastguard Worker 
162*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_cmpxchg(_v, _old, _new) (\
163*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(char)    ? _InterlockedCompareExchange8 ((char *)   (_v), (char)   (_new), (char)   (_old)) : \
164*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(short)   ? _InterlockedCompareExchange16((short *)  (_v), (short)  (_new), (short)  (_old)) : \
165*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(long)    ? _InterlockedCompareExchange  ((long *)   (_v), (long)   (_new), (long)   (_old)) : \
166*bbecb9d1SAndroid Build Coastguard Worker    sizeof *(_v) == sizeof(__int64) ? InterlockedCompareExchange64 ((__int64 *)(_v), (__int64)(_new), (__int64)(_old)) : \
167*bbecb9d1SAndroid Build Coastguard Worker                                      (assert(!"should not get here"), 0))
168*bbecb9d1SAndroid Build Coastguard Worker 
169*bbecb9d1SAndroid Build Coastguard Worker #endif
170*bbecb9d1SAndroid Build Coastguard Worker 
171*bbecb9d1SAndroid Build Coastguard Worker #if defined(PIPE_ATOMIC_OS_SOLARIS)
172*bbecb9d1SAndroid Build Coastguard Worker 
173*bbecb9d1SAndroid Build Coastguard Worker #define PIPE_ATOMIC "Solaris OS atomic functions"
174*bbecb9d1SAndroid Build Coastguard Worker 
175*bbecb9d1SAndroid Build Coastguard Worker #include <atomic.h>
176*bbecb9d1SAndroid Build Coastguard Worker #include <assert.h>
177*bbecb9d1SAndroid Build Coastguard Worker 
178*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_set(_v, _i) (*(_v) = (_i))
179*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_read(_v) (*(_v))
180*bbecb9d1SAndroid Build Coastguard Worker 
181*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_zero(v) (\
182*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint8_t)  ? atomic_dec_8_nv ((uint8_t  *)(v)) == 0 : \
183*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint16_t) ? atomic_dec_16_nv((uint16_t *)(v)) == 0 : \
184*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint32_t) ? atomic_dec_32_nv((uint32_t *)(v)) == 0 : \
185*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint64_t) ? atomic_dec_64_nv((uint64_t *)(v)) == 0 : \
186*bbecb9d1SAndroid Build Coastguard Worker                                     (assert(!"should not get here"), 0))
187*bbecb9d1SAndroid Build Coastguard Worker 
188*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc(v) (void) (\
189*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint8_t)  ? atomic_inc_8 ((uint8_t  *)(v)) : \
190*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint16_t) ? atomic_inc_16((uint16_t *)(v)) : \
191*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint32_t) ? atomic_inc_32((uint32_t *)(v)) : \
192*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint64_t) ? atomic_inc_64((uint64_t *)(v)) : \
193*bbecb9d1SAndroid Build Coastguard Worker                                     (assert(!"should not get here"), 0))
194*bbecb9d1SAndroid Build Coastguard Worker 
195*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_inc_return(v) (__typeof(*v))( \
196*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint8_t)  ? atomic_inc_8_nv ((uint8_t  *)(v)) : \
197*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint16_t) ? atomic_inc_16_nv((uint16_t *)(v)) : \
198*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint32_t) ? atomic_inc_32_nv((uint32_t *)(v)) : \
199*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint64_t) ? atomic_inc_64_nv((uint64_t *)(v)) : \
200*bbecb9d1SAndroid Build Coastguard Worker                                     (assert(!"should not get here"), 0))
201*bbecb9d1SAndroid Build Coastguard Worker 
202*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec(v) (void) ( \
203*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint8_t)  ? atomic_dec_8 ((uint8_t  *)(v)) : \
204*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint16_t) ? atomic_dec_16((uint16_t *)(v)) : \
205*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint32_t) ? atomic_dec_32((uint32_t *)(v)) : \
206*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint64_t) ? atomic_dec_64((uint64_t *)(v)) : \
207*bbecb9d1SAndroid Build Coastguard Worker                                     (assert(!"should not get here"), 0))
208*bbecb9d1SAndroid Build Coastguard Worker 
209*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_dec_return(v) (__typeof(*v))( \
210*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint8_t)  ? atomic_dec_8_nv ((uint8_t  *)(v)) : \
211*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint16_t) ? atomic_dec_16_nv((uint16_t *)(v)) : \
212*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint32_t) ? atomic_dec_32_nv((uint32_t *)(v)) : \
213*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint64_t) ? atomic_dec_64_nv((uint64_t *)(v)) : \
214*bbecb9d1SAndroid Build Coastguard Worker                                     (assert(!"should not get here"), 0))
215*bbecb9d1SAndroid Build Coastguard Worker 
216*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add(v, i) (void) ( \
217*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint8_t)  ? atomic_add_8 ((uint8_t  *)(v), (i)) : \
218*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint16_t) ? atomic_add_16((uint16_t *)(v), (i)) : \
219*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint32_t) ? atomic_add_32((uint32_t *)(v), (i)) : \
220*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint64_t) ? atomic_add_64((uint64_t *)(v), (i)) : \
221*bbecb9d1SAndroid Build Coastguard Worker                                     (assert(!"should not get here"), 0))
222*bbecb9d1SAndroid Build Coastguard Worker 
223*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_add_return(v, i) (__typeof(*v)) ( \
224*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint8_t)  ? atomic_add_8_nv ((uint8_t  *)(v), (i)) : \
225*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint16_t) ? atomic_add_16_nv((uint16_t *)(v), (i)) : \
226*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint32_t) ? atomic_add_32_nv((uint32_t *)(v), (i)) : \
227*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint64_t) ? atomic_add_64_nv((uint64_t *)(v), (i)) : \
228*bbecb9d1SAndroid Build Coastguard Worker                                     (assert(!"should not get here"), 0))
229*bbecb9d1SAndroid Build Coastguard Worker 
230*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_cmpxchg(v, old, _new) (__typeof(*v))( \
231*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint8_t)  ? atomic_cas_8 ((uint8_t  *)(v), (uint8_t )(old), (uint8_t )(_new)) : \
232*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint16_t) ? atomic_cas_16((uint16_t *)(v), (uint16_t)(old), (uint16_t)(_new)) : \
233*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint32_t) ? atomic_cas_32((uint32_t *)(v), (uint32_t)(old), (uint32_t)(_new)) : \
234*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*v) == sizeof(uint64_t) ? atomic_cas_64((uint64_t *)(v), (uint64_t)(old), (uint64_t)(_new)) : \
235*bbecb9d1SAndroid Build Coastguard Worker                                     (assert(!"should not get here"), 0))
236*bbecb9d1SAndroid Build Coastguard Worker 
237*bbecb9d1SAndroid Build Coastguard Worker #endif
238*bbecb9d1SAndroid Build Coastguard Worker 
239*bbecb9d1SAndroid Build Coastguard Worker #ifndef PIPE_ATOMIC
240*bbecb9d1SAndroid Build Coastguard Worker #error "No pipe_atomic implementation selected"
241*bbecb9d1SAndroid Build Coastguard Worker #endif
242*bbecb9d1SAndroid Build Coastguard Worker 
243*bbecb9d1SAndroid Build Coastguard Worker #ifndef PIPE_NATIVE_ATOMIC_XCHG
p_atomic_xchg_32(uint32_t * v,uint32_t i)244*bbecb9d1SAndroid Build Coastguard Worker static inline uint32_t p_atomic_xchg_32(uint32_t *v, uint32_t i)
245*bbecb9d1SAndroid Build Coastguard Worker {
246*bbecb9d1SAndroid Build Coastguard Worker    uint32_t actual = p_atomic_read(v);
247*bbecb9d1SAndroid Build Coastguard Worker    uint32_t expected;
248*bbecb9d1SAndroid Build Coastguard Worker    do {
249*bbecb9d1SAndroid Build Coastguard Worker       expected = actual;
250*bbecb9d1SAndroid Build Coastguard Worker       actual = p_atomic_cmpxchg(v, expected, i);
251*bbecb9d1SAndroid Build Coastguard Worker    } while (expected != actual);
252*bbecb9d1SAndroid Build Coastguard Worker    return actual;
253*bbecb9d1SAndroid Build Coastguard Worker }
254*bbecb9d1SAndroid Build Coastguard Worker 
p_atomic_xchg_64(uint64_t * v,uint64_t i)255*bbecb9d1SAndroid Build Coastguard Worker static inline uint64_t p_atomic_xchg_64(uint64_t *v, uint64_t i)
256*bbecb9d1SAndroid Build Coastguard Worker {
257*bbecb9d1SAndroid Build Coastguard Worker    uint64_t actual = p_atomic_read(v);
258*bbecb9d1SAndroid Build Coastguard Worker    uint64_t expected;
259*bbecb9d1SAndroid Build Coastguard Worker    do {
260*bbecb9d1SAndroid Build Coastguard Worker       expected = actual;
261*bbecb9d1SAndroid Build Coastguard Worker       actual = p_atomic_cmpxchg(v, expected, i);
262*bbecb9d1SAndroid Build Coastguard Worker    } while (expected != actual);
263*bbecb9d1SAndroid Build Coastguard Worker    return actual;
264*bbecb9d1SAndroid Build Coastguard Worker }
265*bbecb9d1SAndroid Build Coastguard Worker 
266*bbecb9d1SAndroid Build Coastguard Worker #define p_atomic_xchg(v, i) (__typeof(*(v)))( \
267*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*(v)) == sizeof(uint32_t) ? p_atomic_xchg_32((uint32_t *)(v), (uint32_t)(i)) : \
268*bbecb9d1SAndroid Build Coastguard Worker    sizeof(*(v)) == sizeof(uint64_t) ? p_atomic_xchg_64((uint64_t *)(v), (uint64_t)(i)) : \
269*bbecb9d1SAndroid Build Coastguard Worker                                       (assert(!"should not get here"), 0))
270*bbecb9d1SAndroid Build Coastguard Worker #endif
271*bbecb9d1SAndroid Build Coastguard Worker 
272*bbecb9d1SAndroid Build Coastguard Worker #endif /* U_ATOMIC_H */
273