#ifndef ISC_ATOMIC_H
#define ISC_ATOMIC_H 1
#include <isc/platform.h>
#include <isc/types.h>
#if defined(_AIX)
#include <sys/atomic_op.h>
#define isc_atomic_xadd(p, v) fetch_and_add(p, v)
#define isc_atomic_store(p, v) _clear_lock(p, v)
#ifdef __GNUC__
static inline int
#else
static int
#endif
isc_atomic_cmpxchg(atomic_p p, int old, int new) {
int orig = old;
#ifdef __GNUC__
asm("ics");
#else
__isync();
#endif
if (compare_and_swap(p, &orig, new))
return (old);
return (orig);
}
#elif defined(ISC_PLATFORM_USEGCCASM) || defined(ISC_PLATFORM_USEMACASM)
static inline isc_int32_t
isc_atomic_xadd(isc_int32_t *p, isc_int32_t val) {
isc_int32_t orig;
__asm__ volatile (
#ifdef ISC_PLATFORM_USEMACASM
"1:"
"lwarx r6, 0, %1\n"
"mr %0, r6\n"
"add r6, r6, %2\n"
"stwcx. r6, 0, %1\n"
"bne- 1b"
#else
"1:"
"lwarx 6, 0, %1\n"
"mr %0, 6\n"
"add 6, 6, %2\n"
"stwcx. 6, 0, %1\n"
"bne- 1b"
#endif
: "=&r"(orig)
: "r"(p), "r"(val)
: "r6", "memory"
);
return (orig);
}
static inline void
isc_atomic_store(void *p, isc_int32_t val) {
__asm__ volatile (
#ifdef ISC_PLATFORM_USEMACASM
"1:"
"lwarx r6, 0, %0\n"
"lwz r6, %1\n"
"stwcx. r6, 0, %0\n"
"bne- 1b"
#else
"1:"
"lwarx 6, 0, %0\n"
"lwz 6, %1\n"
"stwcx. 6, 0, %0\n"
"bne- 1b"
#endif
:
: "r"(p), "m"(val)
: "r6", "memory"
);
}
static inline isc_int32_t
isc_atomic_cmpxchg(isc_int32_t *p, isc_int32_t cmpval, isc_int32_t val) {
isc_int32_t orig;
__asm__ volatile (
#ifdef ISC_PLATFORM_USEMACASM
"1:"
"lwarx r6, 0, %1\n"
"mr %0,r6\n"
"cmpw r6, %2\n"
"bne 2f\n"
"mr r6, %3\n"
"stwcx. r6, 0, %1\n"
"bne- 1b\n"
"2:"
#else
"1:"
"lwarx 6, 0, %1\n"
"mr %0,6\n"
"cmpw 6, %2\n"
"bne 2f\n"
"mr 6, %3\n"
"stwcx. 6, 0, %1\n"
"bne- 1b\n"
"2:"
#endif
: "=&r" (orig)
: "r"(p), "r"(cmpval), "r"(val)
: "r6", "memory"
);
return (orig);
}
#else
#error "unsupported compiler. disable atomic ops by --disable-atomic"
#endif
#endif