22#define ZEND_GCC_PREREQ(x, y) \
23 ((__GNUC__ == (x) && __GNUC_MINOR__ >= (y)) || (__GNUC__ > (x)))
26#if __has_feature(c_atomic) && defined(__clang__)
27#define HAVE_C11_ATOMICS 1
28#elif ZEND_GCC_PREREQ(4, 7)
29#define HAVE_GNUC_ATOMICS 1
30#elif defined(__GNUC__)
31#define HAVE_SYNC_ATOMICS 1
32#elif !defined(ZEND_WIN32)
33#define HAVE_NO_ATOMICS 1
42#if defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS)
53#elif defined(HAVE_C11_ATOMICS)
73#ifndef InterlockedExchange8
74#define InterlockedExchange8 _InterlockedExchange8
77#define InterlockedOr8 _InterlockedOr8
79#ifndef InterlockedCompareExchange8
80#define InterlockedCompareExchange8 _InterlockedCompareExchange8
82#ifndef InterlockedExchange
83#define InterlockedExchange _InterlockedExchange
86#define InterlockedOr _InterlockedOr
88#ifndef InterlockedCompareExchange
89#define InterlockedCompareExchange _InterlockedCompareExchange
92#define ZEND_ATOMIC_BOOL_INIT(obj, desired) ((obj)->value = (desired))
93#define ZEND_ATOMIC_INT_INIT(obj, desired) ((obj)->value = (desired))
95#define ZEND_ATOMIC_BOOL_INITIALIZER(desired) {.value = (desired)}
96#define ZEND_ATOMIC_INT_INITIALIZER(desired) {.value = (desired)}
99 return InterlockedExchange8(&obj->
value, desired);
103 return (
int) InterlockedExchange(&obj->
value, desired);
107 bool prev = (bool) InterlockedCompareExchange8(&obj->
value, *expected, desired);
108 if (
prev == *expected) {
117 int prev = (int) InterlockedCompareExchange(&obj->
value, *expected, desired);
118 if (
prev == *expected) {
129 return InterlockedOr8(&obj->
value,
false);
134 return (
int) InterlockedOr(&obj->
value, 0);
138 (
void)InterlockedExchange8(&obj->
value, desired);
142 (
void)InterlockedExchange(&obj->
value, desired);
145#elif defined(HAVE_C11_ATOMICS)
147#define ZEND_ATOMIC_BOOL_INIT(obj, desired) __c11_atomic_init(&(obj)->value, (desired))
148#define ZEND_ATOMIC_INT_INIT(obj, desired) __c11_atomic_init(&(obj)->value, (desired))
150#define ZEND_ATOMIC_BOOL_INITIALIZER(desired) {.value = (desired)}
151#define ZEND_ATOMIC_INT_INITIALIZER(desired) {.value = (desired)}
154 return __c11_atomic_exchange(&obj->
value, desired, __ATOMIC_SEQ_CST);
158 return __c11_atomic_exchange(&obj->
value, desired, __ATOMIC_SEQ_CST);
162 return __c11_atomic_compare_exchange_strong(&obj->
value, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
166 return __c11_atomic_compare_exchange_strong(&obj->
value, expected, desired, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
170 return __c11_atomic_load(&obj->
value, __ATOMIC_SEQ_CST);
174 return __c11_atomic_load(&obj->
value, __ATOMIC_SEQ_CST);
178 __c11_atomic_store(&obj->
value, desired, __ATOMIC_SEQ_CST);
182 __c11_atomic_store(&obj->
value, desired, __ATOMIC_SEQ_CST);
185#elif defined(HAVE_GNUC_ATOMICS)
189#define ZEND_ATOMIC_BOOL_INIT(obj, desired) ((obj)->value = (desired))
190#define ZEND_ATOMIC_INT_INIT(obj, desired) ((obj)->value = (desired))
192#define ZEND_ATOMIC_BOOL_INITIALIZER(desired) {.value = (desired)}
193#define ZEND_ATOMIC_INT_INITIALIZER(desired) {.value = (desired)}
197 __atomic_exchange(&obj->
value, &desired, &
prev, __ATOMIC_SEQ_CST);
203 __atomic_exchange(&obj->
value, &desired, &
prev, __ATOMIC_SEQ_CST);
208 return __atomic_compare_exchange(&obj->
value, expected, &desired,
false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
212 return __atomic_compare_exchange(&obj->
value, expected, &desired,
false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
217 __atomic_load(&obj->
value, &
prev, __ATOMIC_SEQ_CST);
223 __atomic_load(&obj->
value, &
prev, __ATOMIC_SEQ_CST);
228 __atomic_store(&obj->
value, &desired, __ATOMIC_SEQ_CST);
232 __atomic_store(&obj->
value, &desired, __ATOMIC_SEQ_CST);
235#elif defined(HAVE_SYNC_ATOMICS)
237#define ZEND_ATOMIC_BOOL_INIT(obj, desired) ((obj)->value = (desired))
238#define ZEND_ATOMIC_INT_INIT(obj, desired) ((obj)->value = (desired))
240#define ZEND_ATOMIC_BOOL_INITIALIZER(desired) {.value = (desired)}
241#define ZEND_ATOMIC_INT_INITIALIZER(desired) {.value = (desired)}
244 bool prev = __sync_lock_test_and_set(&obj->
value, desired);
249 __sync_synchronize();
254 int prev = __sync_lock_test_and_set(&obj->
value, desired);
259 __sync_synchronize();
264 bool prev = __sync_val_compare_and_swap(&obj->
value, *expected, desired);
265 if (
prev == *expected) {
274 int prev = __sync_val_compare_and_swap(&obj->
value, *expected, desired);
275 if (
prev == *expected) {
285 return __sync_fetch_and_or(&obj->
value,
false);
290 return __sync_fetch_and_or(&obj->
value, 0);
294 __sync_synchronize();
295 obj->
value = desired;
296 __sync_synchronize();
300 __sync_synchronize();
301 obj->
value = desired;
302 __sync_synchronize();
305#elif defined(HAVE_NO_ATOMICS)
307#warning No atomics support detected. Please open an issue with platform details.
309#define ZEND_ATOMIC_BOOL_INIT(obj, desired) ((obj)->value = (desired))
310#define ZEND_ATOMIC_INT_INIT(obj, desired) ((obj)->value = (desired))
312#define ZEND_ATOMIC_BOOL_INITIALIZER(desired) {.value = (desired)}
313#define ZEND_ATOMIC_INT_INITIALIZER(desired) {.value = (desired)}
316 obj->
value = desired;
320 obj->
value = desired;
325 if (
prev == *expected) {
326 obj->
value = desired;
336 if (
prev == *expected) {
337 obj->
value = desired;
355 obj->
value = desired;
361 obj->
value = desired;
379#if defined(ZEND_WIN32) || defined(HAVE_SYNC_ATOMICS)
prev(array|object &$array)
ZEND_API void zend_atomic_bool_store(zend_atomic_bool *obj, bool desired)
ZEND_API int zend_atomic_int_load(const zend_atomic_int *obj)
ZEND_API bool zend_atomic_int_compare_exchange(zend_atomic_int *obj, int *expected, int desired)
ZEND_API bool zend_atomic_bool_exchange(zend_atomic_bool *obj, bool desired)
struct zend_atomic_int_s zend_atomic_int
ZEND_API void zend_atomic_int_store(zend_atomic_int *obj, int desired)
ZEND_API bool zend_atomic_bool_load(const zend_atomic_bool *obj)
ZEND_API void zend_atomic_bool_init(zend_atomic_bool *obj, bool desired)
ZEND_API int zend_atomic_int_exchange(zend_atomic_int *obj, int desired)
ZEND_API void zend_atomic_int_init(zend_atomic_int *obj, int desired)
ZEND_API bool zend_atomic_bool_compare_exchange(zend_atomic_bool *obj, bool *expected, bool desired)
struct zend_atomic_bool_s zend_atomic_bool
ZEND_API void(ZEND_FASTCALL *zend_touch_vm_stack_data)(void *vm_stack_data)
#define zend_always_inline