#include <stdint.h>
#include <windows.h>
+#include <intrin.h>
+
+#define InterlockedCompareExchange8 _InterlockedCompareExchange8
+
#include <isc/util.h>
#ifndef __ATOMIC_RELAXED
typedef enum memory_order memory_order;
+/*
+ * If you add a type with different sizeof() length,
+ * you need to implement atomic_<foo>_explicitNN macros.
+ */
+
+typedef bool volatile atomic_bool;
+typedef int_fast8_t volatile atomic_int_fast8_t;
+typedef uint_fast8_t volatile atomic_uint_fast8_t;
typedef int_fast32_t volatile atomic_int_fast32_t;
typedef uint_fast32_t volatile atomic_uint_fast32_t;
typedef int_fast64_t volatile atomic_int_fast64_t;
#define atomic_init(obj, desired) \
(*(obj) = (desired))
+#define atomic_store_explicit8(obj, desired, order) \
+ (void)InterlockedExchange8((atomic_int_fast8_t *)obj, desired)
+
#define atomic_store_explicit32(obj, desired, order) \
(order == memory_order_relaxed \
? (void)InterlockedExchangeNoFence((atomic_int_fast32_t *)obj, desired) \
? atomic_store_explicit64(obj, desired, order) \
: (sizeof(*(obj)) == 4 \
? atomic_store_explicit32(obj, desired, order) \
- : atomic_store_abort()))
+ : (sizeof(*(obj)) == 1 \
+ ? atomic_store_explicit8(obj, desired, order) \
+ : atomic_store_abort())))
#define atomic_store(obj, desired) \
atomic_store_explicit(obj, desired, memory_order_seq_cst)
-#define atomic_load_explicit32(obj, order) \
- (order == memory_order_relaxed \
+#define atomic_load_explicit8(obj, order) \
+ (int8_t)InterlockedOr8((atomic_int_fast8_t *)obj, 0)
+
+#define atomic_load_explicit32(obj, order) \
+ (order == memory_order_relaxed \
? (int32_t)InterlockedOrNoFence((atomic_int_fast32_t *)obj, 0) \
- : (order == memory_order_acquire \
- ? (int32_t)InterlockedOrAcquire((atomic_int_fast32_t *)obj, 0) \
- : (order == memory_order_release \
+ : (order == memory_order_acquire \
+ ? (int32_t)InterlockedOrAcquire((atomic_int_fast32_t *)obj, 0) \
+ : (order == memory_order_release \
? (int32_t)InterlockedOrRelease((atomic_int_fast32_t *)obj, 0) \
: (int32_t)InterlockedOr((atomic_int_fast32_t *)obj, 0))))
#ifdef _WIN64
-#define atomic_load_explicit64(obj, order) \
- (order == memory_order_relaxed \
+#define atomic_load_explicit64(obj, order) \
+ (order == memory_order_relaxed \
? InterlockedOr64NoFence((atomic_int_fast64_t *)obj, 0) \
- : (order == memory_order_acquire \
+ : (order == memory_order_acquire \
? InterlockedOr64Acquire((atomic_int_fast64_t *)obj, 0) \
- : (order == memory_order_release \
+ : (order == memory_order_release \
? InterlockedOr64Release((atomic_int_fast64_t *)obj, 0) \
: InterlockedOr64((atomic_int_fast64_t *)obj, 0))))
#else
-#define atomic_load_explicit64(obj, order) \
+#define atomic_load_explicit64(obj, order) \
InterlockedOr64((atomic_int_fast64_t *)obj, 0)
#endif
#define atomic_load_explicit(obj, order) \
(sizeof(*(obj)) == 8 \
? atomic_load_explicit64(obj, order) \
- : (sizeof(*obj == 4) \
+ : (sizeof(*(obj) == 4) \
? atomic_load_explicit32(obj, order) \
- : atomic_load_abort()))
+ : (sizeof(*(obj) == 1) \
+ ? atomic_load_explicit8(obj, order) \
+ : atomic_load_abort())))
#define atomic_load(obj) \
atomic_load_explicit(obj, memory_order_seq_cst)
+#define atomic_fetch_add_explicit8(obj, arg, order) \
+ InterlockedExchangeAdd8((atomic_int_fast8_t *)obj, arg)
+
#define atomic_fetch_add_explicit32(obj, arg, order) \
(order == memory_order_relaxed \
? InterlockedExchangeAddNoFence((atomic_int_fast32_t *)obj, arg) \
? atomic_fetch_add_explicit64(obj, arg, order) \
: (sizeof(*(obj)) == 4 \
? atomic_fetch_add_explicit32(obj, arg, order) \
- : atomic_add_abort()))
+ : (sizeof(*(obj)) == 1 \
+ ? atomic_fetch_add_explicit8(obj, arg, order) \
+ : atomic_add_abort())))
#define atomic_fetch_add(obj, arg) \
atomic_fetch_add_explicit(obj, arg, memory_order_seq_cst)
#define atomic_fetch_sub(obj, arg) \
atomic_fetch_sub_explicit(obj, arg, memory_order_seq_cst)
+static inline bool
+atomic_compare_exchange_strong_explicit8(atomic_int_fast8_t *obj,
+ int8_t *expected,
+ int8_t desired,
+ memory_order succ,
+ memory_order fail)
+{
+ bool __r;
+ int8_t __v;
+ REQUIRE(succ == fail);
+ __v = InterlockedCompareExchange8((atomic_int_fast8_t *)obj, desired, *expected);
+ __r = (*(expected) == __v);
+ if (!__r) {
+ *(expected) = __v;
+ }
+ return (__r);
+}
+
static inline bool
atomic_compare_exchange_strong_explicit32(atomic_int_fast32_t *obj,
int32_t *expected,
? atomic_compare_exchange_strong_explicit32(obj, expected, \
desired, \
succ, fail) \
- : atomic_compare_exchange_abort()))
+ : (sizeof(*(obj)) == 1 \
+ ? atomic_compare_exchange_strong_explicit8(obj, expected, \
+ desired, \
+ succ, fail) \
+ : atomic_compare_exchange_abort())))
#define atomic_compare_exchange_strong(obj, expected, desired, \
succ, fail) \