/* tmememory.h
 *
 * This is an automatically generated file - please modify 'configure.ac'.
 */
#ifndef _TMEMEMORY_H
#define _TMEMEMORY_H
#define TME_MEMORY_TYPE_COMMON long
#ifdef TME_HAVE_INT128_T
#define TME_MEMORY_BUS_BOUNDARY sizeof(tme_uint128_t)
#else
#define TME_MEMORY_BUS_BOUNDARY sizeof(tme_uint64_t)
#endif

#define TME_MEMORY_BARRIER_READ_BEFORE_READ	(0)
#define TME_MEMORY_BARRIER_WRITE_BEFORE_WRITE	(0)
#define TME_MEMORY_BARRIER_READ_BEFORE_WRITE	(0)
#define TME_MEMORY_BARRIER_WRITE_BEFORE_READ	(0)

#define check_align_min(mem,type,align_min) 	(__tme_predict_true(TME_MEMORY_ALIGNMENT_ATOMIC(TME_MEMORY_TYPE_COMMON) != 0 	      && TME_MEMORY_ALIGNMENT_ATOMIC(type) != 0               && _tme_memory_address_test(mem, TME_MEMORY_ALIGNMENT_ATOMIC(type) - 1, align_min) == 0))

#if __GNUC__ > 3 && __GNUC_MINOR__ > 7
#define tme_memory_barrier(address, size, barrier) __atomic_thread_fence(__ATOMIC_SEQ_CST)

#define TME_MEMORY_ALIGNMENT_ATOMIC(type) ((__atomic_always_lock_free(sizeof(type), 0)) ? (sizeof(type)) : (0))

#define tme_memory_atomic_add8(mem,val,lock,align_min) (check_align_min(mem,tme_uint8_t,align_min) ? (__atomic_fetch_add(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_add8(mem,val,lock,align_min)))
#define tme_memory_atomic_sub8(mem,val,lock,align_min) (check_align_min(mem,tme_uint8_t,align_min) ? (__atomic_fetch_sub(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_sub8(mem,val,lock,align_min)))
#define tme_memory_atomic_and8(mem,val,lock,align_min) (check_align_min(mem,tme_uint8_t,align_min) ? (__atomic_fetch_and(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_and8(mem,val,lock,align_min)))
#define tme_memory_atomic_or8(mem,val,lock,align_min) (check_align_min(mem,tme_uint8_t,align_min) ? (__atomic_fetch_or(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_or8(mem,val,lock,align_min)))
#define tme_memory_atomic_xor8(mem,val,lock,align_min) (check_align_min(mem,tme_uint8_t,align_min) ? (__atomic_fetch_xor(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xor8(mem,val,lock,align_min)))
#define tme_memory_atomic_not8(mem,lock,align_min) (check_align_min(mem,tme_uint8_t,align_min) ? (__atomic_fetch_nand(mem,(uint8_t)-1,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_not8(mem,lock,align_min)))
#define tme_memory_atomic_xchg8(mem,val,lock,align_min) (check_align_min(mem,tme_uint8_t,align_min) ? (__atomic_exchange_n(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xchg8(mem,val,lock,align_min)))

static inline
tme_uint8_t _tme_memory_atomic_cx8(tme_shared tme_uint8_t *mem, tme_uint8_t value_read, tme_uint8_t value_written) {
  tme_uint8_t tmp;

  tmp=value_read;
  __atomic_compare_exchange_n(mem, &tmp, value_written, FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);

  return tmp;
}

#define tme_memory_atomic_cx8(mem,valr,valw,lock,align_min) (check_align_min(mem,tme_uint8_t,align_min) ? (_tme_memory_atomic_cx8(mem,valr,valw)) : (tme_memory_atomic_cx8(mem,valr,valw,lock,align_min)))

#define tme_memory_atomic_add16(mem,val,lock,align_min) (check_align_min(mem,tme_uint16_t,align_min) ? (__atomic_fetch_add(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_add16(mem,val,lock,align_min)))
#define tme_memory_atomic_sub16(mem,val,lock,align_min) (check_align_min(mem,tme_uint16_t,align_min) ? (__atomic_fetch_sub(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_sub16(mem,val,lock,align_min)))
#define tme_memory_atomic_and16(mem,val,lock,align_min) (check_align_min(mem,tme_uint16_t,align_min) ? (__atomic_fetch_and(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_and16(mem,val,lock,align_min)))
#define tme_memory_atomic_or16(mem,val,lock,align_min) (check_align_min(mem,tme_uint16_t,align_min) ? (__atomic_fetch_or(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_or16(mem,val,lock,align_min)))
#define tme_memory_atomic_xor16(mem,val,lock,align_min) (check_align_min(mem,tme_uint16_t,align_min) ? (__atomic_fetch_xor(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xor16(mem,val,lock,align_min)))
#define tme_memory_atomic_not16(mem,lock,align_min) (check_align_min(mem,tme_uint16_t,align_min) ? (__atomic_fetch_nand(mem,(uint16_t)-1,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_not16(mem,lock,align_min)))
#define tme_memory_atomic_xchg16(mem,val,lock,align_min) (check_align_min(mem,tme_uint16_t,align_min) ? (__atomic_exchange_n(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xchg16(mem,val,lock,align_min)))

static inline
tme_uint16_t _tme_memory_atomic_cx16(tme_shared tme_uint16_t *mem, tme_uint16_t value_read, tme_uint16_t value_written) {
  tme_uint16_t tmp;

  tmp=value_read;
  __atomic_compare_exchange_n(mem, &tmp, value_written, FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);

  return tmp;
}

#define tme_memory_atomic_cx16(mem,valr,valw,lock,align_min) (check_align_min(mem,tme_uint16_t,align_min) ? (_tme_memory_atomic_cx16(mem,valr,valw)) : (tme_memory_atomic_cx16(mem,valr,valw,lock,align_min)))

#define tme_memory_atomic_add32(mem,val,lock,align_min) (check_align_min(mem,tme_uint32_t,align_min) ? (__atomic_fetch_add(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_add32(mem,val,lock,align_min)))
#define tme_memory_atomic_sub32(mem,val,lock,align_min) (check_align_min(mem,tme_uint32_t,align_min) ? (__atomic_fetch_sub(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_sub32(mem,val,lock,align_min)))
#define tme_memory_atomic_and32(mem,val,lock,align_min) (check_align_min(mem,tme_uint32_t,align_min) ? (__atomic_fetch_and(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_and32(mem,val,lock,align_min)))
#define tme_memory_atomic_or32(mem,val,lock,align_min) (check_align_min(mem,tme_uint32_t,align_min) ? (__atomic_fetch_or(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_or32(mem,val,lock,align_min)))
#define tme_memory_atomic_xor32(mem,val,lock,align_min) (check_align_min(mem,tme_uint32_t,align_min) ? (__atomic_fetch_xor(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xor32(mem,val,lock,align_min)))
#define tme_memory_atomic_not32(mem,lock,align_min) (check_align_min(mem,tme_uint32_t,align_min) ? (__atomic_fetch_nand(mem,(uint32_t)-1,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_not32(mem,lock,align_min)))
#define tme_memory_atomic_xchg32(mem,val,lock,align_min) (check_align_min(mem,tme_uint32_t,align_min) ? (__atomic_exchange_n(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xchg32(mem,val,lock,align_min)))

static inline
tme_uint32_t _tme_memory_atomic_cx32(tme_shared tme_uint32_t *mem, tme_uint32_t value_read, tme_uint32_t value_written) {
  tme_uint32_t tmp;

  tmp=value_read;
  __atomic_compare_exchange_n(mem, &tmp, value_written, FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);

  return tmp;
}

#define tme_memory_atomic_cx32(mem,valr,valw,lock,align_min) (check_align_min(mem,tme_uint32_t,align_min) ? (_tme_memory_atomic_cx32(mem,valr,valw)) : (tme_memory_atomic_cx32(mem,valr,valw,lock,align_min)))

#define tme_memory_atomic_add64(mem,val,lock,align_min) (check_align_min(mem,tme_uint64_t,align_min) ? (__atomic_fetch_add(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_add64(mem,val,lock,align_min)))
#define tme_memory_atomic_sub64(mem,val,lock,align_min) (check_align_min(mem,tme_uint64_t,align_min) ? (__atomic_fetch_sub(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_sub64(mem,val,lock,align_min)))
#define tme_memory_atomic_and64(mem,val,lock,align_min) (check_align_min(mem,tme_uint64_t,align_min) ? (__atomic_fetch_and(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_and64(mem,val,lock,align_min)))
#define tme_memory_atomic_or64(mem,val,lock,align_min) (check_align_min(mem,tme_uint64_t,align_min) ? (__atomic_fetch_or(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_or64(mem,val,lock,align_min)))
#define tme_memory_atomic_xor64(mem,val,lock,align_min) (check_align_min(mem,tme_uint64_t,align_min) ? (__atomic_fetch_xor(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xor64(mem,val,lock,align_min)))
#define tme_memory_atomic_not64(mem,lock,align_min) (check_align_min(mem,tme_uint64_t,align_min) ? (__atomic_fetch_nand(mem,(uint64_t)-1,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_not64(mem,lock,align_min)))
#define tme_memory_atomic_xchg64(mem,val,lock,align_min) (check_align_min(mem,tme_uint64_t,align_min) ? (__atomic_exchange_n(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xchg64(mem,val,lock,align_min)))

static inline
tme_uint64_t _tme_memory_atomic_cx64(tme_shared tme_uint64_t *mem, tme_uint64_t value_read, tme_uint64_t value_written) {
  tme_uint64_t tmp;

  tmp=value_read;
  __atomic_compare_exchange_n(mem, &tmp, value_written, FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);

  return tmp;
}

#define tme_memory_atomic_cx64(mem,valr,valw,lock,align_min) (check_align_min(mem,tme_uint64_t,align_min) ? (_tme_memory_atomic_cx64(mem,valr,valw)) : (tme_memory_atomic_cx64(mem,valr,valw,lock,align_min)))

#ifdef TME_HAVE_INT128_T
#define tme_memory_atomic_add128(mem,val,lock,align_min) (check_align_min(mem,tme_uint128_t,align_min) ? (__atomic_fetch_add(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_add128(mem,val,lock,align_min)))
#define tme_memory_atomic_sub128(mem,val,lock,align_min) (check_align_min(mem,tme_uint128_t,align_min) ? (__atomic_fetch_sub(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_sub128(mem,val,lock,align_min)))
#define tme_memory_atomic_and128(mem,val,lock,align_min) (check_align_min(mem,tme_uint128_t,align_min) ? (__atomic_fetch_and(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_and128(mem,val,lock,align_min)))
#define tme_memory_atomic_or128(mem,val,lock,align_min) (check_align_min(mem,tme_uint128_t,align_min) ? (__atomic_fetch_or(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_or128(mem,val,lock,align_min)))
#define tme_memory_atomic_xor128(mem,val,lock,align_min) (check_align_min(mem,tme_uint128_t,align_min) ? (__atomic_fetch_xor(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xor128(mem,val,lock,align_min)))
#define tme_memory_atomic_not128(mem,lock,align_min) (check_align_min(mem,tme_uint128_t,align_min) ? (__atomic_fetch_nand(mem,(uint128_t)-1,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_not128(mem,lock,align_min)))
#define tme_memory_atomic_xchg128(mem,val,lock,align_min) (check_align_min(mem,tme_uint128_t,align_min) ? (__atomic_exchange_n(mem,val,__ATOMIC_SEQ_CST)) : (tme_memory_atomic_xchg128(mem,val,lock,align_min)))

static inline
tme_uint128_t _tme_memory_atomic_cx128(tme_shared tme_uint128_t *mem, tme_uint128_t value_read, tme_uint128_t value_written) {
  tme_uint128_t tmp;

  tmp=value_read;
  __atomic_compare_exchange_n(mem, &tmp, value_written, FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);

  return tmp;
}

#define tme_memory_atomic_cx128(mem,valr,valw,lock,align_min) (check_align_min(mem,tme_uint128_t,align_min) ? (_tme_memory_atomic_cx128(mem,valr,valw)) : (tme_memory_atomic_cx128(mem,valr,valw,lock,align_min)))

#endif // TME_HAVE_INT128_T
#else // __GNUC__
#define tme_memory_barrier(address, size, barrier) __sync_synchronize()
#define TME_MEMORY_ALIGNMENT_ATOMIC(type) ((sizeof(type) <= TME_MEMORY_BUS_BOUNDARY) ? (sizeof(type)) : (0))
#endif // !__GNUC__
#endif /* !_TMEMEMORY_H */
