diff options
author | eeight <eeight@yandex-team.ru> | 2022-05-17 10:20:05 +0300 |
---|---|---|
committer | eeight <eeight@yandex-team.ru> | 2022-05-17 10:20:05 +0300 |
commit | f3ec69ca4abe595abc22fe786710538cfc9b016a (patch) | |
tree | 02f8e499b2bcfbe70a927dc23801ce2264110688 | |
parent | 7f57a1b674d2b1cd7b35ed078e00e3b656e7f25f (diff) | |
download | ydb-f3ec69ca4abe595abc22fe786710538cfc9b016a.tar.gz |
IGNIETFERRO-1105 Use std::atomic in spinlock
ref:dca14f354fc9b9698f83663ceb0e62e797fe98c5
-rw-r--r-- | util/system/atexit.cpp | 2 | ||||
-rw-r--r-- | util/system/guard.h | 1 | ||||
-rw-r--r-- | util/system/spinlock.h | 102 |
3 files changed, 49 insertions, 56 deletions
diff --git a/util/system/atexit.cpp b/util/system/atexit.cpp index 74fb10b6b1..aeb29466b3 100644 --- a/util/system/atexit.cpp +++ b/util/system/atexit.cpp @@ -76,7 +76,7 @@ namespace { TPriorityQueue<TFunc*, TVector<TFunc*>, TCmp> Items_; }; - static TAtomic atExitLock = 0; + static TAdaptiveLock atExitLock; static TAtExit* volatile atExitPtr = nullptr; alignas(TAtExit) static char atExitMem[sizeof(TAtExit)]; diff --git a/util/system/guard.h b/util/system/guard.h index efc091d5f8..b6ca45fff6 100644 --- a/util/system/guard.h +++ b/util/system/guard.h @@ -1,6 +1,7 @@ #pragma once #include <util/generic/noncopyable.h> +#include <util/system/defaults.h> template <class T> struct TCommonLockOps { diff --git a/util/system/spinlock.h b/util/system/spinlock.h index af2630890a..3fbe8a6441 100644 --- a/util/system/spinlock.h +++ b/util/system/spinlock.h @@ -1,21 +1,34 @@ #pragma once -#include "atomic.h" #include "spin_wait.h" +#include <atomic> + class TSpinLockBase { protected: - inline TSpinLockBase() noexcept { - AtomicSet(Val_, 0); + TSpinLockBase() = default; + + // These were unearthed in IGNIETFERRO-1105 + // Need to get rid of them separately + TSpinLockBase(const TSpinLockBase& other) + : Val_(other.Val_.load()) + { + } + + TSpinLockBase& operator=(const TSpinLockBase& other) + { + Val_.store(other.Val_); + return *this; } public: inline bool IsLocked() const noexcept { - return AtomicGet(Val_); + return Val_.load(); } inline bool TryAcquire() noexcept { - return AtomicTryLock(&Val_); + intptr_t zero = 0; + return Val_.compare_exchange_strong(zero, 1); } inline bool try_lock() noexcept { @@ -23,7 +36,7 @@ public: } protected: - TAtomic Val_; + std::atomic<intptr_t> Val_{0}; }; static inline void SpinLockPause() { @@ -37,18 +50,6 @@ static inline void SpinLockPause() { #endif } -static inline void AcquireSpinLock(TAtomic* l) { - if (!AtomicTryLock(l)) { - do { - SpinLockPause(); - } while (!AtomicTryAndTryLock(l)); - } -} - -static inline void ReleaseSpinLock(TAtomic* l) { - AtomicUnlock(l); -} - /* * You should almost always use TAdaptiveLock instead of TSpinLock */ @@ -57,11 +58,19 @@ public: using TSpinLockBase::TSpinLockBase; inline void Release() noexcept { - ReleaseSpinLock(&Val_); + Val_.store(0, std::memory_order_release); } inline void Acquire() noexcept { - AcquireSpinLock(&Val_); + intptr_t zero = 0; + if (Val_.compare_exchange_strong(zero, 1)) { + return; + } + do { + SpinLockPause(); + zero = 0; + } while (Val_.load(std::memory_order_acquire) != 0 || + !Val_.compare_exchange_strong(zero, 1)); } inline void unlock() noexcept { @@ -73,30 +82,30 @@ public: } }; -static inline void AcquireAdaptiveLock(TAtomic* l) { - if (!AtomicTryLock(l)) { - TSpinWait sw; - - while (!AtomicTryAndTryLock(l)) { - sw.Sleep(); - } - } -} - -static inline void ReleaseAdaptiveLock(TAtomic* l) { - AtomicUnlock(l); -} - class TAdaptiveLock: public TSpinLockBase { public: using TSpinLockBase::TSpinLockBase; - inline void Release() noexcept { - ReleaseAdaptiveLock(&Val_); + void Release() noexcept { + Val_.store(0, std::memory_order_release); } - inline void Acquire() noexcept { - AcquireAdaptiveLock(&Val_); + void Acquire() noexcept { + intptr_t zero = 0; + if (Val_.compare_exchange_strong(zero, 1)) { + return; + } + + TSpinWait sw; + + for (;;) { + zero = 0; + if (Val_.load(std::memory_order_acquire) == 0 && + Val_.compare_exchange_strong(zero, 1)) { + break; + } + sw.Sleep(); + } } inline void unlock() noexcept { @@ -107,20 +116,3 @@ public: Acquire(); } }; - -#include "guard.h" - -template <> -struct TCommonLockOps<TAtomic> { - static inline void Acquire(TAtomic* v) noexcept { - AcquireAdaptiveLock(v); - } - - static inline bool TryAcquire(TAtomic* v) noexcept { - return AtomicTryLock(v); - } - - static inline void Release(TAtomic* v) noexcept { - ReleaseAdaptiveLock(v); - } -}; |