#ifndef AWS_COMMON_ATOMICS_GNU_OLD_INL
#define AWS_COMMON_ATOMICS_GNU_OLD_INL
#include <aws/common/atomics.h>
#include <aws/common/common.h>
#include <stdint.h>
#include <stdlib.h>
AWS_EXTERN_C_BEGIN
#if defined(__GNUC__)
# if (__GNUC__ < 4)
# error GCC versions before 4.1.2 are not supported
# elif (defined(__arm__) || defined(__ia64__)) && (__GNUC__ == 4 && __GNUC_MINOR__ < 4)
# error GCC versions before 4.4.0 are not supported on ARM or Itanium
# elif (defined(__x86_64__) || defined(__i386__)) && \
(__GNUC__ == 4 && (__GNUC_MINOR__ < 1 || (__GNUC_MINOR__ == 1 && __GNUC_PATCHLEVEL__ < 2)))
# error GCC versions before 4.1.2 are not supported on x86/x64
# endif
#endif
typedef size_t aws_atomic_impl_int_t;
static inline void aws_atomic_private_compiler_barrier(void) {
__asm__ __volatile__("" : : : "memory");
}
static inline void aws_atomic_private_barrier_before(enum aws_memory_order order) {
if (order == aws_memory_order_release || order == aws_memory_order_acq_rel || order == aws_memory_order_seq_cst) {
__sync_synchronize();
}
aws_atomic_private_compiler_barrier();
}
static inline void aws_atomic_private_barrier_after(enum aws_memory_order order) {
aws_atomic_private_compiler_barrier();
if (order == aws_memory_order_acquire || order == aws_memory_order_acq_rel || order == aws_memory_order_seq_cst) {
__sync_synchronize();
}
}
AWS_STATIC_IMPL
void aws_atomic_init_int(volatile struct aws_atomic_var *var, size_t n) {
AWS_ATOMIC_VAR_INTVAL(var) = n;
}
AWS_STATIC_IMPL
void aws_atomic_init_ptr(volatile struct aws_atomic_var *var, void *p) {
AWS_ATOMIC_VAR_PTRVAL(var) = p;
}
AWS_STATIC_IMPL
size_t aws_atomic_load_int_explicit(volatile const struct aws_atomic_var *var, enum aws_memory_order memory_order) {
aws_atomic_private_barrier_before(memory_order);
size_t retval = AWS_ATOMIC_VAR_INTVAL(var);
aws_atomic_private_compiler_barrier();
return retval;
}
AWS_STATIC_IMPL
void *aws_atomic_load_ptr_explicit(volatile const struct aws_atomic_var *var, enum aws_memory_order memory_order) {
aws_atomic_private_barrier_before(memory_order);
void *retval = AWS_ATOMIC_VAR_PTRVAL(var);
aws_atomic_private_compiler_barrier();
return retval;
}
AWS_STATIC_IMPL
void aws_atomic_store_int_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order memory_order) {
aws_atomic_private_compiler_barrier();
AWS_ATOMIC_VAR_INTVAL(var) = n;
aws_atomic_private_barrier_after(memory_order);
}
AWS_STATIC_IMPL
void aws_atomic_store_ptr_explicit(volatile struct aws_atomic_var *var, void *p, enum aws_memory_order memory_order) {
aws_atomic_private_compiler_barrier();
AWS_ATOMIC_VAR_PTRVAL(var) = p;
aws_atomic_private_barrier_after(memory_order);
}
AWS_STATIC_IMPL
size_t aws_atomic_exchange_int_explicit(
volatile struct aws_atomic_var *var,
size_t n,
enum aws_memory_order memory_order) {
size_t oldval;
do {
oldval = AWS_ATOMIC_VAR_INTVAL(var);
} while (!__sync_bool_compare_and_swap(&AWS_ATOMIC_VAR_INTVAL(var), oldval, n));
return oldval;
}
AWS_STATIC_IMPL
void *aws_atomic_exchange_ptr_explicit(
volatile struct aws_atomic_var *var,
void *p,
enum aws_memory_order memory_order) {
void *oldval;
do {
oldval = AWS_ATOMIC_VAR_PTRVAL(var);
} while (!__sync_bool_compare_and_swap(&AWS_ATOMIC_VAR_PTRVAL(var), oldval, p));
return oldval;
}
AWS_STATIC_IMPL
bool aws_atomic_compare_exchange_int_explicit(
volatile struct aws_atomic_var *var,
size_t *expected,
size_t desired,
enum aws_memory_order order_success,
enum aws_memory_order order_failure) {
bool result = __sync_bool_compare_and_swap(&AWS_ATOMIC_VAR_INTVAL(var), *expected, desired);
if (!result) {
*expected = AWS_ATOMIC_VAR_INTVAL(var);
}
return result;
}
AWS_STATIC_IMPL
bool aws_atomic_compare_exchange_ptr_explicit(
volatile struct aws_atomic_var *var,
void **expected,
void *desired,
enum aws_memory_order order_success,
enum aws_memory_order order_failure) {
bool result = __sync_bool_compare_and_swap(&AWS_ATOMIC_VAR_PTRVAL(var), *expected, desired);
if (!result) {
*expected = AWS_ATOMIC_VAR_PTRVAL(var);
}
return result;
}
AWS_STATIC_IMPL
size_t aws_atomic_fetch_add_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
return __sync_fetch_and_add(&AWS_ATOMIC_VAR_INTVAL(var), n);
}
AWS_STATIC_IMPL
size_t aws_atomic_fetch_sub_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
return __sync_fetch_and_sub(&AWS_ATOMIC_VAR_INTVAL(var), n);
}
AWS_STATIC_IMPL
size_t aws_atomic_fetch_or_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
return __sync_fetch_and_or(&AWS_ATOMIC_VAR_INTVAL(var), n);
}
AWS_STATIC_IMPL
size_t aws_atomic_fetch_and_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
return __sync_fetch_and_and(&AWS_ATOMIC_VAR_INTVAL(var), n);
}
AWS_STATIC_IMPL
size_t aws_atomic_fetch_xor_explicit(volatile struct aws_atomic_var *var, size_t n, enum aws_memory_order order) {
return __sync_fetch_and_xor(&AWS_ATOMIC_VAR_INTVAL(var), n);
}
AWS_STATIC_IMPL
void aws_atomic_thread_fence(enum aws_memory_order order) {
__sync_synchronize();
}
#define AWS_ATOMICS_HAVE_THREAD_FENCE
AWS_EXTERN_C_END
#endif