2 * Many similar implementations exist. See for example libwsbm
3 * or the linux kernel include/atomic.h
5 * No copyright claimed on this file.
14 /* Favor OS-provided implementations.
16 * Where no OS-provided implementation is available, fall back to
17 * locally coded assembly, compiler intrinsic or ultimately a
18 * mutex-based implementation.
21 #define PIPE_ATOMIC_OS_SOLARIS
22 #elif defined(_MSC_VER)
23 #define PIPE_ATOMIC_MSVC_INTRINSIC
24 #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 401)
25 #define PIPE_ATOMIC_GCC_INTRINSIC
27 #error "Unsupported platform"
31 /* Implementation using GCC-provided synchronization intrinsics
33 #if defined(PIPE_ATOMIC_GCC_INTRINSIC)
35 #define PIPE_ATOMIC "GCC Sync Intrinsics"
41 #define p_atomic_set(_v, _i) (*(_v) = (_i))
42 #define p_atomic_read(_v) (*(_v))
45 p_atomic_dec_zero(int32_t *v
)
47 return (__sync_sub_and_fetch(v
, 1) == 0);
51 p_atomic_inc(int32_t *v
)
53 (void) __sync_add_and_fetch(v
, 1);
57 p_atomic_dec(int32_t *v
)
59 (void) __sync_sub_and_fetch(v
, 1);
63 p_atomic_inc_return(int32_t *v
)
65 return __sync_add_and_fetch(v
, 1);
69 p_atomic_dec_return(int32_t *v
)
71 return __sync_sub_and_fetch(v
, 1);
75 p_atomic_cmpxchg(int32_t *v
, int32_t old
, int32_t _new
)
77 return __sync_val_compare_and_swap(v
, old
, _new
);
88 /* Unlocked version for single threaded environments, such as some
89 * windows kernel modules.
91 #if defined(PIPE_ATOMIC_OS_UNLOCKED)
93 #define PIPE_ATOMIC "Unlocked"
95 #define p_atomic_set(_v, _i) (*(_v) = (_i))
96 #define p_atomic_read(_v) (*(_v))
97 #define p_atomic_dec_zero(_v) ((bool) --(*(_v)))
98 #define p_atomic_inc(_v) ((void) (*(_v))++)
99 #define p_atomic_dec(_v) ((void) (*(_v))--)
100 #define p_atomic_inc_return(_v) ((*(_v))++)
101 #define p_atomic_dec_return(_v) ((*(_v))--)
102 #define p_atomic_cmpxchg(_v, old, _new) (*(_v) == old ? *(_v) = (_new) : *(_v))
107 #if defined(PIPE_ATOMIC_MSVC_INTRINSIC)
109 #define PIPE_ATOMIC "MSVC Intrinsics"
113 #pragma intrinsic(_InterlockedIncrement)
114 #pragma intrinsic(_InterlockedDecrement)
115 #pragma intrinsic(_InterlockedCompareExchange)
121 #define p_atomic_set(_v, _i) (*(_v) = (_i))
122 #define p_atomic_read(_v) (*(_v))
125 p_atomic_dec_zero(int32_t *v
)
127 return _InterlockedDecrement((long *)v
) == 0;
131 p_atomic_inc(int32_t *v
)
133 _InterlockedIncrement((long *)v
);
136 static inline int32_t
137 p_atomic_inc_return(int32_t *v
)
139 return _InterlockedIncrement((long *)v
);
143 p_atomic_dec(int32_t *v
)
145 _InterlockedDecrement((long *)v
);
148 static inline int32_t
149 p_atomic_dec_return(int32_t *v
)
151 return _InterlockedDecrement((long *)v
);
154 static inline int32_t
155 p_atomic_cmpxchg(int32_t *v
, int32_t old
, int32_t _new
)
157 return _InterlockedCompareExchange((long *)v
, _new
, old
);
166 #if defined(PIPE_ATOMIC_OS_SOLARIS)
168 #define PIPE_ATOMIC "Solaris OS atomic functions"
176 #define p_atomic_set(_v, _i) (*(_v) = (_i))
177 #define p_atomic_read(_v) (*(_v))
180 p_atomic_dec_zero(int32_t *v
)
182 uint32_t n
= atomic_dec_32_nv((uint32_t *) v
);
187 #define p_atomic_inc(_v) atomic_inc_32((uint32_t *) _v)
188 #define p_atomic_dec(_v) atomic_dec_32((uint32_t *) _v)
189 #define p_atomic_inc_return(_v) atomic_inc_32_nv((uint32_t *) _v)
190 #define p_atomic_dec_return(_v) atomic_dec_32_nv((uint32_t *) _v)
192 #define p_atomic_cmpxchg(_v, _old, _new) \
193 atomic_cas_32( (uint32_t *) _v, (uint32_t) _old, (uint32_t) _new)
203 #error "No pipe_atomic implementation selected"
208 #endif /* U_ATOMIC_H */