/// \copyright SPDX-License-Identifier: Apache-2.0 /// \author Леонид Юрьев aka Leonid Yuriev \date 2015-2024 #pragma once #include "essentials.h" #ifndef MDBX_64BIT_ATOMIC #error "The MDBX_64BIT_ATOMIC must be defined before" #endif /* MDBX_64BIT_ATOMIC */ #ifndef MDBX_64BIT_CAS #error "The MDBX_64BIT_CAS must be defined before" #endif /* MDBX_64BIT_CAS */ #if defined(__cplusplus) && !defined(__STDC_NO_ATOMICS__) && __has_include() #include #define MDBX_HAVE_C11ATOMICS #elif !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L || __has_extension(c_atomic)) && \ !defined(__STDC_NO_ATOMICS__) && \ (__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || !(defined(__GNUC__) || defined(__clang__))) #include #define MDBX_HAVE_C11ATOMICS #elif defined(__GNUC__) || defined(__clang__) #elif defined(_MSC_VER) #pragma warning(disable : 4163) /* 'xyz': not available as an intrinsic */ #pragma warning(disable : 4133) /* 'function': incompatible types - from \ 'size_t' to 'LONGLONG' */ #pragma warning(disable : 4244) /* 'return': conversion from 'LONGLONG' to \ 'std::size_t', possible loss of data */ #pragma warning(disable : 4267) /* 'function': conversion from 'size_t' to \ 'long', possible loss of data */ #pragma intrinsic(_InterlockedExchangeAdd, _InterlockedCompareExchange) #pragma intrinsic(_InterlockedExchangeAdd64, _InterlockedCompareExchange64) #elif defined(__APPLE__) #include #else #error FIXME atomic-ops #endif typedef enum mdbx_memory_order { mo_Relaxed, mo_AcquireRelease /* , mo_SequentialConsistency */ } mdbx_memory_order_t; typedef union { volatile uint32_t weak; #ifdef MDBX_HAVE_C11ATOMICS volatile _Atomic uint32_t c11a; #endif /* MDBX_HAVE_C11ATOMICS */ } mdbx_atomic_uint32_t; typedef union { volatile uint64_t weak; #if defined(MDBX_HAVE_C11ATOMICS) && (MDBX_64BIT_CAS || MDBX_64BIT_ATOMIC) volatile _Atomic uint64_t c11a; #endif #if !defined(MDBX_HAVE_C11ATOMICS) || !MDBX_64BIT_CAS || !MDBX_64BIT_ATOMIC __anonymous_struct_extension__ struct { #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ mdbx_atomic_uint32_t low, high; #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ mdbx_atomic_uint32_t high, low; #else #error "FIXME: Unsupported byte order" #endif /* __BYTE_ORDER__ */ }; #endif } mdbx_atomic_uint64_t; #ifdef MDBX_HAVE_C11ATOMICS /* Crutches for C11 atomic compiler's bugs */ #if defined(__e2k__) && defined(__LCC__) && __LCC__ < /* FIXME */ 127 #define MDBX_c11a_ro(type, ptr) (&(ptr)->weak) #define MDBX_c11a_rw(type, ptr) (&(ptr)->weak) #elif defined(__clang__) && __clang__ < 8 #define MDBX_c11a_ro(type, ptr) ((volatile _Atomic(type) *)&(ptr)->c11a) #define MDBX_c11a_rw(type, ptr) (&(ptr)->c11a) #else #define MDBX_c11a_ro(type, ptr) (&(ptr)->c11a) #define MDBX_c11a_rw(type, ptr) (&(ptr)->c11a) #endif /* Crutches for C11 atomic compiler's bugs */ #define mo_c11_store(fence) \ (((fence) == mo_Relaxed) ? memory_order_relaxed \ : ((fence) == mo_AcquireRelease) ? memory_order_release \ : memory_order_seq_cst) #define mo_c11_load(fence) \ (((fence) == mo_Relaxed) ? memory_order_relaxed \ : ((fence) == mo_AcquireRelease) ? memory_order_acquire \ : memory_order_seq_cst) #endif /* MDBX_HAVE_C11ATOMICS */ #define SAFE64_INVALID_THRESHOLD UINT64_C(0xffffFFFF00000000)