mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-30 22:47:16 +08:00
mdbx: fix/refine the use of C11 atomics.
Change-Id: I5d925d4625b06296fd82f4b35ee36be682e7b2d3
This commit is contained in:
parent
041a4c0aa5
commit
62da4db09a
1
.github/actions/spelling/expect.txt
vendored
1
.github/actions/spelling/expect.txt
vendored
@ -208,6 +208,7 @@ csrc
|
|||||||
CSRSS
|
CSRSS
|
||||||
css
|
css
|
||||||
cstdarg
|
cstdarg
|
||||||
|
cstdatomic
|
||||||
cstddef
|
cstddef
|
||||||
cstdint
|
cstdint
|
||||||
cstr
|
cstr
|
||||||
|
66
src/core.c
66
src/core.c
@ -780,12 +780,24 @@ static __always_inline void atomic_yield(void) {
|
|||||||
#if MDBX_64BIT_CAS
|
#if MDBX_64BIT_CAS
|
||||||
static __always_inline bool atomic_cas64(volatile uint64_t *p, uint64_t c,
|
static __always_inline bool atomic_cas64(volatile uint64_t *p, uint64_t c,
|
||||||
uint64_t v) {
|
uint64_t v) {
|
||||||
#if defined(ATOMIC_VAR_INIT) || defined(ATOMIC_LLONG_LOCK_FREE)
|
#if !defined(__STDC_NO_ATOMICS__) && \
|
||||||
|
(defined(ATOMIC_VAR_INIT) || defined(ATOMIC_LLONG_LOCK_FREE) || \
|
||||||
|
__has_extension(c_atomic))
|
||||||
STATIC_ASSERT(sizeof(long long) >= sizeof(uint64_t));
|
STATIC_ASSERT(sizeof(long long) >= sizeof(uint64_t));
|
||||||
#ifndef __COVERITY__
|
#ifdef ATOMIC_LLONG_LOCK_FREE
|
||||||
STATIC_ASSERT(atomic_is_lock_free(p));
|
STATIC_ASSERT(ATOMIC_LLONG_LOCK_FREE > 0);
|
||||||
#endif /* Workaround for Coverity */
|
#if ATOMIC_LLONG_LOCK_FREE < 2
|
||||||
return atomic_compare_exchange_strong((_Atomic uint64_t *)p, &c, v);
|
assert(atomic_is_lock_free(p));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
assert(atomic_is_lock_free(p));
|
||||||
|
#endif
|
||||||
|
#ifdef __clang__
|
||||||
|
STATIC_ASSERT(sizeof(_Atomic uint64_t) == sizeof(uint64_t));
|
||||||
|
return atomic_compare_exchange_strong((_Atomic volatile uint64_t *)p, &c, v);
|
||||||
|
#else
|
||||||
|
return atomic_compare_exchange_strong(p, &c, v);
|
||||||
|
#endif
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
return __sync_bool_compare_and_swap(p, c, v);
|
return __sync_bool_compare_and_swap(p, c, v);
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
@ -801,12 +813,24 @@ static __always_inline bool atomic_cas64(volatile uint64_t *p, uint64_t c,
|
|||||||
|
|
||||||
static __always_inline bool atomic_cas32(volatile uint32_t *p, uint32_t c,
|
static __always_inline bool atomic_cas32(volatile uint32_t *p, uint32_t c,
|
||||||
uint32_t v) {
|
uint32_t v) {
|
||||||
#if defined(ATOMIC_VAR_INIT) || defined(ATOMIC_INT_LOCK_FREE)
|
#if !defined(__STDC_NO_ATOMICS__) && \
|
||||||
|
(defined(ATOMIC_VAR_INIT) || defined(ATOMIC_INT_LOCK_FREE) || \
|
||||||
|
__has_extension(c_atomic))
|
||||||
STATIC_ASSERT(sizeof(int) >= sizeof(uint32_t));
|
STATIC_ASSERT(sizeof(int) >= sizeof(uint32_t));
|
||||||
#ifndef __COVERITY__
|
#ifdef ATOMIC_INT_LOCK_FREE
|
||||||
STATIC_ASSERT(atomic_is_lock_free(p));
|
STATIC_ASSERT(ATOMIC_INT_LOCK_FREE > 0);
|
||||||
#endif /* Workaround for Coverity */
|
#if ATOMIC_INT_LOCK_FREE < 2
|
||||||
return atomic_compare_exchange_strong((_Atomic uint32_t *)p, &c, v);
|
assert(atomic_is_lock_free(p));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
assert(atomic_is_lock_free(p));
|
||||||
|
#endif
|
||||||
|
#ifdef __clang__
|
||||||
|
STATIC_ASSERT(sizeof(_Atomic uint32_t) == sizeof(uint32_t));
|
||||||
|
return atomic_compare_exchange_strong((_Atomic volatile uint32_t *)p, &c, v);
|
||||||
|
#else
|
||||||
|
return atomic_compare_exchange_strong(p, &c, v);
|
||||||
|
#endif
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
return __sync_bool_compare_and_swap(p, c, v);
|
return __sync_bool_compare_and_swap(p, c, v);
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
@ -820,12 +844,24 @@ static __always_inline bool atomic_cas32(volatile uint32_t *p, uint32_t c,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static __always_inline uint32_t atomic_add32(volatile uint32_t *p, uint32_t v) {
|
static __always_inline uint32_t atomic_add32(volatile uint32_t *p, uint32_t v) {
|
||||||
#if defined(ATOMIC_VAR_INIT) || defined(ATOMIC_INT_LOCK_FREE)
|
#if !defined(__STDC_NO_ATOMICS__) && \
|
||||||
|
(defined(ATOMIC_VAR_INIT) || defined(ATOMIC_INT_LOCK_FREE) || \
|
||||||
|
__has_extension(c_atomic))
|
||||||
STATIC_ASSERT(sizeof(int) >= sizeof(uint32_t));
|
STATIC_ASSERT(sizeof(int) >= sizeof(uint32_t));
|
||||||
#ifndef __COVERITY__
|
#ifdef ATOMIC_INT_LOCK_FREE
|
||||||
STATIC_ASSERT(atomic_is_lock_free(p));
|
STATIC_ASSERT(ATOMIC_INT_LOCK_FREE > 0);
|
||||||
#endif /* Workaround for Coverity */
|
#if ATOMIC_INT_LOCK_FREE < 2
|
||||||
return atomic_fetch_add((_Atomic uint32_t *)p, v);
|
assert(atomic_is_lock_free(p));
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
assert(atomic_is_lock_free(p));
|
||||||
|
#endif
|
||||||
|
#ifdef __clang__
|
||||||
|
STATIC_ASSERT(sizeof(_Atomic uint32_t) == sizeof(uint32_t));
|
||||||
|
return atomic_fetch_add((_Atomic volatile uint32_t *)p, v);
|
||||||
|
#else
|
||||||
|
return atomic_fetch_add(p, v);
|
||||||
|
#endif
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
return __sync_fetch_and_add(p, v);
|
return __sync_fetch_and_add(p, v);
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
|
59
src/osal.h
59
src/osal.h
@ -459,6 +459,35 @@ typedef union MDBX_srwlock {
|
|||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern void mdbx_osal_jitter(bool tiny);
|
extern void mdbx_osal_jitter(bool tiny);
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/* Atomics */
|
||||||
|
|
||||||
|
#if defined(__cplusplus) && !defined(__STDC_NO_ATOMICS__) && __has_include(<cstdatomic>)
|
||||||
|
#include <cstdatomic>
|
||||||
|
#elif !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L) && \
|
||||||
|
!defined(__STDC_NO_ATOMICS__) && \
|
||||||
|
(__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || \
|
||||||
|
!(defined(__GNUC__) || defined(__clang__)))
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
/* LY: nothing required */
|
||||||
|
#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 <libkern/OSAtomic.h>
|
||||||
|
#else
|
||||||
|
#error FIXME atomic-ops
|
||||||
|
#endif
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
/* Memory/Compiler barriers, cache coherence */
|
/* Memory/Compiler barriers, cache coherence */
|
||||||
|
|
||||||
@ -500,8 +529,8 @@ static __maybe_unused __inline void mdbx_compiler_barrier(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static __maybe_unused __inline void mdbx_memory_barrier(void) {
|
static __maybe_unused __inline void mdbx_memory_barrier(void) {
|
||||||
#if __has_extension(c_atomic) || __has_extension(cxx_atomic)
|
#if __has_extension(c_atomic) && !defined(__STDC_NO_ATOMICS__)
|
||||||
__c11_atomic_thread_fence(__ATOMIC_SEQ_CST);
|
atomic_thread_fence(__ATOMIC_SEQ_CST);
|
||||||
#elif defined(__ATOMIC_SEQ_CST)
|
#elif defined(__ATOMIC_SEQ_CST)
|
||||||
__atomic_thread_fence(__ATOMIC_SEQ_CST);
|
__atomic_thread_fence(__ATOMIC_SEQ_CST);
|
||||||
#elif defined(__clang__) || defined(__GNUC__)
|
#elif defined(__clang__) || defined(__GNUC__)
|
||||||
@ -898,32 +927,6 @@ MDBX_INTERNAL_VAR MDBX_RegGetValueA mdbx_RegGetValueA;
|
|||||||
|
|
||||||
#endif /* Windows */
|
#endif /* Windows */
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
|
||||||
/* Atomics */
|
|
||||||
|
|
||||||
#if !defined(__cplusplus) && (__STDC_VERSION__ >= 201112L) && \
|
|
||||||
!defined(__STDC_NO_ATOMICS__) && \
|
|
||||||
(__GNUC_PREREQ(4, 9) || __CLANG_PREREQ(3, 8) || \
|
|
||||||
!(defined(__GNUC__) || defined(__clang__)))
|
|
||||||
#include <stdatomic.h>
|
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
|
||||||
/* LY: nothing required */
|
|
||||||
#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 <libkern/OSAtomic.h>
|
|
||||||
#else
|
|
||||||
#error FIXME atomic-ops
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif /* !__cplusplus */
|
#endif /* !__cplusplus */
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user