diff --git a/core/os/spin_lock.h b/core/os/spin_lock.h index d386cd589052..fa345ff3418f 100644 --- a/core/os/spin_lock.h +++ b/core/os/spin_lock.h @@ -52,19 +52,35 @@ class SpinLock { #else +#include "core/os/thread.h" + #include +#include -class SpinLock { - mutable std::atomic_flag locked = ATOMIC_FLAG_INIT; +static_assert(std::atomic_bool::is_always_lock_free); + +class alignas(Thread::CACHE_LINE_BYTES) SpinLock { + mutable std::atomic_bool locked = ATOMIC_VAR_INIT(false); public: _ALWAYS_INLINE_ void lock() const { - while (locked.test_and_set(std::memory_order_acquire)) { - // Continue. + while (true) { + bool expected = false; + if (locked.compare_exchange_weak(expected, true, std::memory_order_acq_rel, std::memory_order_relaxed)) { + break; + } + do { + std::this_thread::yield(); + } while (locked.load(std::memory_order_relaxed)); } } + _ALWAYS_INLINE_ void unlock() const { - locked.clear(std::memory_order_release); + locked.store(false, std::memory_order_release); + } + + _ALWAYS_INLINE_ void acquire() const { + (void)locked.load(std::memory_order_acquire); } }; diff --git a/core/os/thread.h b/core/os/thread.h index a0ecc24c9165..d83b00aafcb6 100644 --- a/core/os/thread.h +++ b/core/os/thread.h @@ -85,6 +85,12 @@ class Thread { void (*term)() = nullptr; }; +#ifdef __cpp_lib_hardware_interference_size + static const size_t CACHE_LINE_BYTES = std::hardware_constructive_interference_size; +#else + static const size_t CACHE_LINE_BYTES = 64; +#endif + private: friend class Main;