[*] Brute force atomic ordering on foreign architectures

This commit is contained in:
Reece Wilson 2023-08-24 21:49:26 +01:00
parent 2e93ca7e32
commit cda2c02de6

View File

@ -350,11 +350,17 @@ template <class T>
inline auline T AuAtomicUtils<T>::Load(T *in) inline auline T AuAtomicUtils<T>::Load(T *in)
{ {
#if defined(AURORA_COMPILER_MSVC) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86)) #if defined(AURORA_COMPILER_MSVC) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
::_ReadWriteBarrier(); ::_ReadWriteBarrier(); // compile-time only! we use this to prevent optimizations. x86/64 does not care so long as we're aligned.
return *in; return *in;
#elif defined(AURORA_COMPILER_MSVC) #elif defined(AURORA_COMPILER_MSVC)
::MemoryBarrier(); // works on all legacy MSVC targets including AMD64, IA64, and POWER
return *in; return *in;
#else #else
#if defined(AURORA_COMPILER_CLANG)
#if !(defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
__sync_synchronize(); // brute force on unknown archs. gcc-like compilers will accept this
#endif
if constexpr (AuIsSame_v<AuUInt8, T>) if constexpr (AuIsSame_v<AuUInt8, T>)
{ {
return ATOMIC_PREFIX_HAX(atomic_load)((atomic_uint_fast8_t *)in, __ATOMIC_ACQUIRE); return ATOMIC_PREFIX_HAX(atomic_load)((atomic_uint_fast8_t *)in, __ATOMIC_ACQUIRE);
@ -383,7 +389,10 @@ inline auline T AuAtomicUtils<T>::Load(T *in)
{ {
static_assert(AuIsVoid_v<T>, "T"); static_assert(AuIsVoid_v<T>, "T");
} }
#endif #else
return __sync_val_compare_and_swap(*in, 0, 0);
#endif
#endif
} }
template <class T> template <class T>
@ -391,9 +400,9 @@ inline auline void AuAtomicUtils<T>::Store(T *in, T val)
{ {
#if defined(AURORA_COMPILER_MSVC) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86)) #if defined(AURORA_COMPILER_MSVC) && (defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
*in = val; *in = val;
::_ReadWriteBarrier();
#elif defined(AURORA_COMPILER_MSVC) #elif defined(AURORA_COMPILER_MSVC)
*in = val; *in = val;
::MemoryBarrier();
#else #else
if constexpr (AuIsSame_v<AuUInt8, T>) if constexpr (AuIsSame_v<AuUInt8, T>)
{ {
@ -423,6 +432,9 @@ inline auline void AuAtomicUtils<T>::Store(T *in, T val)
{ {
static_assert(AuIsVoid_v<T>, "T"); static_assert(AuIsVoid_v<T>, "T");
} }
#if !(defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
__sync_synchronize();
#endif
#endif #endif
} }
@ -434,9 +446,13 @@ void AuAtomicUtils<AuUInt8>::ClearU8Lock(AuUInt8 *in)
*in = 0; *in = 0;
::_ReadWriteBarrier(); ::_ReadWriteBarrier();
#elif defined(AURORA_COMPILER_MSVC) #elif defined(AURORA_COMPILER_MSVC)
// i think this will work on aarch64 and most risc architectures
InterlockedAndRelease((volatile LONG *)in, ~0xFF); InterlockedAndRelease((volatile LONG *)in, ~0xFF);
#else #else
ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast8_t *)in, 0, __ATOMIC_RELEASE); ATOMIC_PREFIX_HAX(atomic_store)((atomic_uint_fast8_t *)in, 0, __ATOMIC_RELEASE);
#if !(defined(AURORA_ARCH_X64) || defined(AURORA_ARCH_X86))
__sync_synchronize();
#endif
#endif #endif
} }