#ifndef _DB_ATOMIC_H_
#define _DB_ATOMIC_H_
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(DB_WIN32)
typedef DWORD atomic_value_t;
#else
typedef int32_t atomic_value_t;
#endif
#if defined(DB_WINCE)
typedef struct {
volatile atomic_value_t value;
volatile atomic_value_t dummy;
} db_atomic_t;
#else
typedef struct {
volatile atomic_value_t value;
} db_atomic_t;
#endif
#define atomic_read(p) ((p)->value)
#define atomic_init(p, val) ((p)->value = (val))
#ifdef HAVE_ATOMIC_SUPPORT
#if defined(DB_WIN32)
#if defined(DB_WINCE)
#define WINCE_ATOMIC_MAGIC(p) \
\
(p)->dummy = 0
#else
#define WINCE_ATOMIC_MAGIC(p) 0
#endif
#if defined(DB_WINCE) || (defined(_MSC_VER) && _MSC_VER < 1300)
typedef PLONG interlocked_val;
#define atomic_inc(env, p) \
(WINCE_ATOMIC_MAGIC(p), \
InterlockedIncrement((interlocked_val)(&(p)->value)))
#else
typedef LONG volatile *interlocked_val;
#define atomic_inc(env, p) \
InterlockedIncrement((interlocked_val)(&(p)->value))
#endif
#define atomic_dec(env, p) \
(WINCE_ATOMIC_MAGIC(p), \
InterlockedDecrement((interlocked_val)(&(p)->value)))
#if defined(_MSC_VER) && _MSC_VER < 1300
#define atomic_compare_exchange(env, p, oldval, newval) \
(WINCE_ATOMIC_MAGIC(p), \
(InterlockedCompareExchange((PVOID *)(&(p)->value), \
(PVOID)(newval), (PVOID)(oldval)) == (PVOID)(oldval)))
#else
#define atomic_compare_exchange(env, p, oldval, newval) \
(WINCE_ATOMIC_MAGIC(p), \
(InterlockedCompareExchange((interlocked_val)(&(p)->value), \
(newval), (oldval)) == (oldval)))
#endif
#endif
#if defined(HAVE_ATOMIC_SOLARIS)
#include <atomic.h>
#define atomic_inc(env, p) \
atomic_inc_uint_nv((volatile unsigned int *) &(p)->value)
#define atomic_dec(env, p) \
atomic_dec_uint_nv((volatile unsigned int *) &(p)->value)
#define atomic_compare_exchange(env, p, oval, nval) \
(atomic_cas_32((volatile unsigned int *) &(p)->value, \
(oval), (nval)) == (oval))
#endif
#if defined(HAVE_ATOMIC_X86_GCC_ASSEMBLY)
#define atomic_inc(env, p) __atomic_inc(p)
#define atomic_dec(env, p) __atomic_dec(p)
#define atomic_compare_exchange(env, p, o, n) \
__atomic_compare_exchange((p), (o), (n))
static inline int __atomic_inc(db_atomic_t *p)
{
int temp;
temp = 1;
__asm__ __volatile__("lock; xadd %0, (%1)"
: "+r"(temp)
: "r"(p));
return (temp + 1);
}
static inline int __atomic_dec(db_atomic_t *p)
{
int temp;
temp = -1;
__asm__ __volatile__("lock; xadd %0, (%1)"
: "+r"(temp)
: "r"(p));
return (temp - 1);
}
static inline int __atomic_compare_exchange(
db_atomic_t *p, atomic_value_t oldval, atomic_value_t newval)
{
atomic_value_t was;
if (p->value != oldval)
return 0;
__asm__ __volatile__("lock; cmpxchgl %1, (%2);"
:"=a"(was)
:"r"(newval), "r"(p), "a"(oldval)
:"memory", "cc");
return (was == oldval);
}
#endif
#else
#ifndef HAVE_MUTEX_SUPPORT
#define atomic_inc(env, p) (++(p)->value)
#define atomic_dec(env, p) (--(p)->value)
#define atomic_compare_exchange(env, p, oldval, newval) \
(DB_ASSERT(env, atomic_read(p) == (oldval)), \
atomic_init(p, (newval)), 1)
#else
#define atomic_inc(env, p) __atomic_inc(env, p)
#define atomic_dec(env, p) __atomic_dec(env, p)
#endif
#endif
#if defined(__cplusplus)
}
#endif
#endif