Files
bind9/lib/isc/win32/include/isc/stdatomic.h
T

602 lines
22 KiB
C

/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <intrin.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <uchar.h>
#include <windows.h>
#pragma warning(disable : 4133)
#pragma warning(disable : 4090)
#define InterlockedExchangeAdd8 _InterlockedExchangeAdd8
#define InterlockedCompareExchange8 _InterlockedCompareExchange8
#pragma intrinsic(_InterlockedCompareExchange8, _InterlockedExchangeAdd8)
#include <isc/util.h>
#define ATOMIC_VAR_INIT(x) x
#ifndef __ATOMIC_RELAXED
#define __ATOMIC_RELAXED 0
#endif /* ifndef __ATOMIC_RELAXED */
#ifndef __ATOMIC_CONSUME
#define __ATOMIC_CONSUME 1
#endif /* ifndef __ATOMIC_CONSUME */
#ifndef __ATOMIC_ACQUIRE
#define __ATOMIC_ACQUIRE 2
#endif /* ifndef __ATOMIC_ACQUIRE */
#ifndef __ATOMIC_RELEASE
#define __ATOMIC_RELEASE 3
#endif /* ifndef __ATOMIC_RELEASE */
#ifndef __ATOMIC_ACQ_REL
#define __ATOMIC_ACQ_REL 4
#endif /* ifndef __ATOMIC_ACQ_REL */
#ifndef __ATOMIC_SEQ_CST
#define __ATOMIC_SEQ_CST 5
#endif /* ifndef __ATOMIC_SEQ_CST */
enum memory_order {
memory_order_relaxed = __ATOMIC_RELAXED,
memory_order_consume = __ATOMIC_CONSUME,
memory_order_acquire = __ATOMIC_ACQUIRE,
memory_order_release = __ATOMIC_RELEASE,
memory_order_acq_rel = __ATOMIC_ACQ_REL,
memory_order_seq_cst = __ATOMIC_SEQ_CST
};
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 char volatile atomic_char;
typedef signed char volatile atomic_schar;
typedef unsigned char volatile atomic_uchar;
typedef short volatile atomic_short;
typedef unsigned short volatile atomic_ushort;
typedef int volatile atomic_int;
typedef unsigned int volatile atomic_uint;
typedef long volatile atomic_long;
typedef unsigned long volatile atomic_ulong;
typedef long long volatile atomic_llong;
typedef unsigned long long volatile atomic_ullong;
typedef char16_t volatile atomic_char16_t;
typedef char32_t volatile atomic_char32_t;
typedef wchar_t volatile atomic_wchar_t;
typedef int_least8_t volatile atomic_int_least8_t;
typedef uint_least8_t volatile atomic_uint_least8_t;
typedef int_least16_t volatile atomic_int_least16_t;
typedef uint_least16_t volatile atomic_uint_least16_t;
typedef int_least32_t volatile atomic_int_least32_t;
typedef uint_least32_t volatile atomic_uint_least32_t;
typedef int_least64_t volatile atomic_int_least64_t;
typedef uint_least64_t volatile atomic_uint_least64_t;
typedef int_fast8_t volatile atomic_int_fast8_t;
typedef uint_fast8_t volatile atomic_uint_fast8_t;
typedef int_fast16_t volatile atomic_int_fast16_t;
typedef uint_fast16_t volatile atomic_uint_fast16_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;
typedef uint_fast64_t volatile atomic_uint_fast64_t;
typedef intptr_t volatile atomic_intptr_t;
typedef uintptr_t volatile atomic_uintptr_t;
typedef size_t volatile atomic_size_t;
typedef ptrdiff_t volatile atomic_ptrdiff_t;
typedef intmax_t volatile atomic_intmax_t;
typedef uintmax_t volatile atomic_uintmax_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_explicit16(obj, desired, order) \
(order == memory_order_relaxed \
? (void)InterlockedExchangeNoFence16((atomic_short *)obj, \
desired) \
: (order == memory_order_acquire \
? (void)InterlockedExchangeAcquire16( \
(atomic_short *)obj, desired) \
: (void)InterlockedExchange16((atomic_short *)obj, \
desired)))
#define atomic_store_explicit32(obj, desired, order) \
(order == memory_order_relaxed \
? (void)InterlockedExchangeNoFence( \
(atomic_int_fast32_t *)obj, desired) \
: (order == memory_order_acquire \
? (void)InterlockedExchangeAcquire( \
(atomic_int_fast32_t *)obj, desired) \
: (void)InterlockedExchange( \
(atomic_int_fast32_t *)obj, desired)))
#ifdef _WIN64
#define atomic_store_explicit64(obj, desired, order) \
(order == memory_order_relaxed \
? (void)InterlockedExchangeNoFence64( \
(atomic_int_fast64_t *)obj, desired) \
: (order == memory_order_acquire \
? (void)InterlockedExchangeAcquire64( \
(atomic_int_fast64_t *)obj, desired) \
: (void)InterlockedExchange64( \
(atomic_int_fast64_t *)obj, desired)))
#else /* ifdef _WIN64 */
#define atomic_store_explicit64(obj, desired, order) \
(void)InterlockedExchange64((atomic_int_fast64_t *)obj, desired)
#endif /* ifdef _WIN64 */
static inline void
atomic_store_abort(void) {
INSIST(0);
ISC_UNREACHABLE();
}
#define atomic_store_explicit(obj, desired, order) \
(sizeof(*(obj)) == 8 \
? atomic_store_explicit64(obj, desired, order) \
: (sizeof(*(obj)) == 4 \
? atomic_store_explicit32(obj, desired, order) \
: (sizeof(*(obj)) == 2 \
? atomic_store_explicit16(obj, desired, \
order) \
: (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_explicit8(obj, order) \
(int8_t) InterlockedOr8((atomic_int_fast8_t *)obj, 0)
#define atomic_load_explicit16(obj, order) \
(short)InterlockedOr16((atomic_short *)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 \
? (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 \
? InterlockedOr64NoFence((atomic_int_fast64_t *)obj, 0) \
: (order == memory_order_acquire \
? InterlockedOr64Acquire( \
(atomic_int_fast64_t *)obj, 0) \
: (order == memory_order_release \
? InterlockedOr64Release( \
(atomic_int_fast64_t *)obj, 0) \
: InterlockedOr64( \
(atomic_int_fast64_t *)obj, \
0))))
#else /* ifdef _WIN64 */
#define atomic_load_explicit64(obj, order) \
InterlockedOr64((atomic_int_fast64_t *)obj, 0)
#endif /* ifdef _WIN64 */
static inline int8_t
atomic_load_abort(void) {
INSIST(0);
ISC_UNREACHABLE();
}
#define atomic_load_explicit(obj, order) \
((sizeof(*(obj)) == 8 \
? atomic_load_explicit64(obj, order) \
: (sizeof(*(obj) == 4) \
? atomic_load_explicit32(obj, order) \
: (sizeof(*(obj) == 2) \
? atomic_load_explicit16(obj, order) \
: (sizeof(*(obj) == 1) \
? atomic_load_explicit8( \
obj, order) \
: atomic_load_abort())))) & \
(sizeof(*(obj)) == 8 \
? 0xffffffffffffffffULL \
: (sizeof(*(obj)) == 4 \
? 0xffffffffULL \
: (sizeof(*(obj)) == 2 \
? 0xffffULL \
: (sizeof(*(obj)) == 1 \
? 0xffULL \
: 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_explicit16(obj, arg, order) \
InterlockedExchangeAdd16((atomic_short *)obj, arg)
#define atomic_fetch_add_explicit32(obj, arg, order) \
(order == memory_order_relaxed \
? InterlockedExchangeAddNoFence((atomic_int_fast32_t *)obj, \
arg) \
: (order == memory_order_acquire \
? InterlockedExchangeAddAcquire( \
(atomic_int_fast32_t *)obj, arg) \
: (order == memory_order_release \
? InterlockedExchangeAddRelease( \
(atomic_int_fast32_t *)obj, \
arg) \
: InterlockedExchangeAdd( \
(atomic_int_fast32_t *)obj, \
arg))))
#ifdef _WIN64
#define atomic_fetch_add_explicit64(obj, arg, order) \
(order == memory_order_relaxed \
? InterlockedExchangeAddNoFence64((atomic_int_fast64_t *)obj, \
arg) \
: (order == memory_order_acquire \
? InterlockedExchangeAddAcquire64( \
(atomic_int_fast64_t *)obj, arg) \
: (order == memory_order_release \
? InterlockedExchangeAddRelease64( \
(atomic_int_fast64_t *)obj, \
arg) \
: InterlockedExchangeAdd64( \
(atomic_int_fast64_t *)obj, \
arg))))
#else /* ifdef _WIN64 */
#define atomic_fetch_add_explicit64(obj, arg, order) \
InterlockedExchangeAdd64((atomic_int_fast64_t *)obj, arg)
#endif /* ifdef _WIN64 */
static inline int8_t
atomic_add_abort(void) {
INSIST(0);
ISC_UNREACHABLE();
}
#define atomic_fetch_add_explicit(obj, arg, order) \
(sizeof(*(obj)) == 8 \
? atomic_fetch_add_explicit64(obj, arg, order) \
: (sizeof(*(obj)) == 4 \
? atomic_fetch_add_explicit32(obj, arg, order) \
: (sizeof(*(obj)) == 2 \
? atomic_fetch_add_explicit16(obj, arg, \
order) \
: (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_explicit(obj, arg, order) \
atomic_fetch_add_explicit(obj, -arg, order)
#define atomic_fetch_sub(obj, arg) \
atomic_fetch_sub_explicit(obj, arg, memory_order_seq_cst)
#define atomic_fetch_and_explicit8(obj, arg, order) \
InterlockedAnd8((atomic_int_fast8_t *)obj, arg)
#define atomic_fetch_and_explicit16(obj, arg, order) \
InterlockedAnd16((atomic_short *)obj, arg)
#define atomic_fetch_and_explicit32(obj, arg, order) \
(order == memory_order_relaxed \
? InterlockedAndNoFence((atomic_int_fast32_t *)obj, arg) \
: (order == memory_order_acquire \
? InterlockedAndAcquire( \
(atomic_int_fast32_t *)obj, arg) \
: (order == memory_order_release \
? InterlockedAndRelease( \
(atomic_int_fast32_t *)obj, \
arg) \
: InterlockedAnd( \
(atomic_int_fast32_t *)obj, \
arg))))
#ifdef _WIN64
#define atomic_fetch_and_explicit64(obj, arg, order) \
(order == memory_order_relaxed \
? InterlockedAnd64NoFence((atomic_int_fast64_t *)obj, arg) \
: (order == memory_order_acquire \
? InterlockedAnd64Acquire( \
(atomic_int_fast64_t *)obj, arg) \
: (order == memory_order_release \
? InterlockedAnd64Release( \
(atomic_int_fast64_t *)obj, \
arg) \
: InterlockedAnd64( \
(atomic_int_fast64_t *)obj, \
arg))))
#else /* ifdef _WIN64 */
#define atomic_fetch_and_explicit64(obj, arg, order) \
InterlockedAnd64((atomic_int_fast64_t *)obj, arg)
#endif /* ifdef _WIN64 */
static inline int8_t
atomic_and_abort(void) {
INSIST(0);
ISC_UNREACHABLE();
}
#define atomic_fetch_and_explicit(obj, arg, order) \
(sizeof(*(obj)) == 8 \
? atomic_fetch_and_explicit64(obj, arg, order) \
: (sizeof(*(obj)) == 4 \
? atomic_fetch_and_explicit32(obj, arg, order) \
: (sizeof(*(obj)) == 2 \
? atomic_fetch_and_explicit16(obj, arg, \
order) \
: (sizeof(*(obj)) == 1 \
? atomic_fetch_and_explicit8( \
obj, arg, order) \
: atomic_and_abort()))))
#define atomic_fetch_and(obj, arg) \
atomic_fetch_and_explicit(obj, arg, memory_order_seq_cst)
#define atomic_fetch_or_explicit8(obj, arg, order) \
InterlockedOr8((atomic_int_fast8_t *)obj, arg)
#define atomic_fetch_or_explicit16(obj, arg, order) \
InterlockedOr16((atomic_short *)obj, arg)
#define atomic_fetch_or_explicit32(obj, arg, order) \
(order == memory_order_relaxed \
? InterlockedOrNoFence((atomic_int_fast32_t *)obj, arg) \
: (order == memory_order_acquire \
? InterlockedOrAcquire((atomic_int_fast32_t *)obj, \
arg) \
: (order == memory_order_release \
? InterlockedOrRelease( \
(atomic_int_fast32_t *)obj, \
arg) \
: InterlockedOr( \
(atomic_int_fast32_t *)obj, \
arg))))
#ifdef _WIN64
#define atomic_fetch_or_explicit64(obj, arg, order) \
(order == memory_order_relaxed \
? InterlockedOr64NoFence((atomic_int_fast64_t *)obj, arg) \
: (order == memory_order_acquire \
? InterlockedOr64Acquire( \
(atomic_int_fast64_t *)obj, arg) \
: (order == memory_order_release \
? InterlockedOr64Release( \
(atomic_int_fast64_t *)obj, \
arg) \
: InterlockedOr64( \
(atomic_int_fast64_t *)obj, \
arg))))
#else /* ifdef _WIN64 */
#define atomic_fetch_or_explicit64(obj, arg, order) \
InterlockedOr64((atomic_int_fast64_t *)obj, arg)
#endif /* ifdef _WIN64 */
static inline int8_t
atomic_or_abort(void) {
INSIST(0);
ISC_UNREACHABLE();
}
#define atomic_fetch_or_explicit(obj, arg, order) \
(sizeof(*(obj)) == 8 \
? atomic_fetch_or_explicit64(obj, arg, order) \
: (sizeof(*(obj)) == 4 \
? atomic_fetch_or_explicit32(obj, arg, order) \
: (sizeof(*(obj)) == 2 \
? atomic_fetch_or_explicit16(obj, arg, \
order) \
: (sizeof(*(obj)) == 1 \
? atomic_fetch_or_explicit8( \
obj, arg, order) \
: atomic_or_abort()))))
#define atomic_fetch_or(obj, arg) \
atomic_fetch_or_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;
UNUSED(succ);
UNUSED(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_explicit16(atomic_short *obj, short *expected,
short desired, memory_order succ,
memory_order fail) {
bool __r;
short __v;
UNUSED(succ);
UNUSED(fail);
__v = InterlockedCompareExchange16((atomic_short *)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, int32_t desired,
memory_order succ,
memory_order fail) {
bool __r;
int32_t __v;
UNUSED(succ);
UNUSED(fail);
switch (succ) {
case memory_order_relaxed:
__v = InterlockedCompareExchangeNoFence(
(atomic_int_fast32_t *)obj, desired, *expected);
break;
case memory_order_acquire:
__v = InterlockedCompareExchangeAcquire(
(atomic_int_fast32_t *)obj, desired, *expected);
break;
case memory_order_release:
__v = InterlockedCompareExchangeRelease(
(atomic_int_fast32_t *)obj, desired, *expected);
break;
default:
__v = InterlockedCompareExchange((atomic_int_fast32_t *)obj,
desired, *expected);
break;
}
__r = (*(expected) == __v);
if (!__r) {
*(expected) = __v;
}
return (__r);
}
static inline bool
atomic_compare_exchange_strong_explicit64(atomic_int_fast64_t *obj,
int64_t *expected, int64_t desired,
memory_order succ,
memory_order fail) {
bool __r;
int64_t __v;
UNUSED(succ);
UNUSED(fail);
#ifdef _WIN64
switch (succ) {
case memory_order_relaxed:
__v = InterlockedCompareExchangeNoFence64(
(atomic_int_fast64_t *)obj, desired, *expected);
break;
case memory_order_acquire:
__v = InterlockedCompareExchangeAcquire64(
(atomic_int_fast64_t *)obj, desired, *expected);
break;
case memory_order_release:
__v = InterlockedCompareExchangeRelease64(
(atomic_int_fast64_t *)obj, desired, *expected);
break;
default:
__v = InterlockedCompareExchange64((atomic_int_fast64_t *)obj,
desired, *expected);
break;
}
#else /* ifdef _WIN64 */
__v = InterlockedCompareExchange64((atomic_int_fast64_t *)obj, desired,
*expected);
#endif /* ifdef _WIN64 */
__r = (*(expected) == __v);
if (!__r) {
*(expected) = __v;
}
return (__r);
}
static inline bool
atomic_compare_exchange_abort(void) {
INSIST(0);
ISC_UNREACHABLE();
}
#define atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, \
fail) \
(sizeof(*(obj)) == 8 \
? atomic_compare_exchange_strong_explicit64( \
obj, expected, desired, succ, fail) \
: (sizeof(*(obj)) == 4 \
? atomic_compare_exchange_strong_explicit32( \
obj, expected, desired, succ, fail) \
: (sizeof(*(obj)) == 2 \
? atomic_compare_exchange_strong_explicit16( \
obj, expected, desired, succ, \
fail) \
: (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) \
atomic_compare_exchange_strong_explicit(obj, expected, desired, \
memory_order_seq_cst, \
memory_order_seq_cst)
#define atomic_compare_exchange_weak_explicit(obj, expected, desired, succ, \
fail) \
atomic_compare_exchange_strong_explicit(obj, expected, desired, succ, \
fail)
#define atomic_compare_exchange_weak(obj, expected, desired) \
atomic_compare_exchange_weak_explicit(obj, expected, desired, \
memory_order_seq_cst, \
memory_order_seq_cst)
static inline bool
atomic_exchange_abort(void) {
INSIST(0);
ISC_UNREACHABLE();
}
#define atomic_exchange_explicit(obj, desired, order) \
(sizeof(*(obj)) == 8 \
? InterlockedExchange64(obj, desired) \
: (sizeof(*(obj)) == 4 \
? InterlockedExchange(obj, desired) \
: (sizeof(*(obj)) == 2 \
? InterlockedExchange16(obj, desired) \
: (sizeof(*(obj)) == 1 \
? InterlockedExchange8( \
obj, desired) \
: atomic_exchange_abort()))))
#define atomic_exchange(obj, desired) \
atomic_exchange_explicit(obj, desired, memory_order_seq_cst)