diff options
author | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2023-11-16 17:24:02 +0300 |
---|---|---|
committer | arkady-e1ppa <arkady-e1ppa@yandex-team.com> | 2023-11-16 18:51:45 +0300 |
commit | 6b40f0f1060a3e9d54347e52c7dc8fb278e6e86b (patch) | |
tree | da4c8447ff495a023682292e1ac90309312ddb8f | |
parent | 8f8023320207d4dfa6e9b6c595fe272382595cdd (diff) | |
download | ydb-6b40f0f1060a3e9d54347e52c7dc8fb278e6e86b.tar.gz |
Active spinlock tracking from pr3151306. Added TracelessGuards to disable mentioned tracking
1) Добавлена возможность инструментировать ваш любимый мьютекс/спинлок/что-либо с методами Acquire/Release со схожим смыслом. Делается это засчет методов ```NThreading::NDetail::RecordSpinlockAcquired```/```NThreading::NDetail::RecordSpinlockReleased```. Они отслеживают число захваченных спинлоков.
2) Добавлен макрос ```REGISTER_TRACKED_SPIN_LOCK_CLASS```, который позволяет номинально проверить на этапе компиляции, что данный спинлок отслеживается.
3) Добавлен метод ```NThreading::VerifyNoSpinlockAffinity```, который коркается, если число захваченных спинлоков больше нуля.
4) Добавлены Traceless версии (почти) всех гардов, чтобы можно было не отслеживать конкретную критическую секцию, если очень нужно.
5) Внутри файберного ```WaitUntilSet``` вызывается ```VerifyNoSpinlockAffinity``` -- делать ```WaitFor``` или ```Yield``` внутри отслеживаемых критических секций нельзя. Если очень хочется -- используем TracelessGuard нужного вида.
6) Теперь отслеживаются такие спинлоки и их наследники: ```TSpinLock```, ```TRecursiveSpinLock```, ```TReaderWriterSpinLock```.
7) Зарегистрированы как отслеживаемые все вышеперечисленные спинлоки и их Padded версии.
8) Все эти действия имеют эффект только в дебаг сборке. В релизе вся эта диагностика стирается.
18 files changed, 342 insertions, 20 deletions
diff --git a/library/cpp/yt/threading/CMakeLists.darwin-x86_64.txt b/library/cpp/yt/threading/CMakeLists.darwin-x86_64.txt index 7dbacb9da4..289553555a 100644 --- a/library/cpp/yt/threading/CMakeLists.darwin-x86_64.txt +++ b/library/cpp/yt/threading/CMakeLists.darwin-x86_64.txt @@ -31,6 +31,7 @@ target_sources(cpp-yt-threading PRIVATE ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/recursive_spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/rw_spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock_base.cpp + ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock_count.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_wait.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_wait_hook.cpp diff --git a/library/cpp/yt/threading/CMakeLists.linux-aarch64.txt b/library/cpp/yt/threading/CMakeLists.linux-aarch64.txt index 644ee262f0..ae9721da48 100644 --- a/library/cpp/yt/threading/CMakeLists.linux-aarch64.txt +++ b/library/cpp/yt/threading/CMakeLists.linux-aarch64.txt @@ -32,6 +32,7 @@ target_sources(cpp-yt-threading PRIVATE ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/recursive_spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/rw_spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock_base.cpp + ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock_count.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_wait.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_wait_hook.cpp diff --git a/library/cpp/yt/threading/CMakeLists.linux-x86_64.txt b/library/cpp/yt/threading/CMakeLists.linux-x86_64.txt index 644ee262f0..ae9721da48 100644 --- a/library/cpp/yt/threading/CMakeLists.linux-x86_64.txt +++ b/library/cpp/yt/threading/CMakeLists.linux-x86_64.txt @@ -32,6 +32,7 @@ target_sources(cpp-yt-threading PRIVATE ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/recursive_spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/rw_spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock_base.cpp + ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock_count.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_wait.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_wait_hook.cpp diff --git a/library/cpp/yt/threading/CMakeLists.windows-x86_64.txt b/library/cpp/yt/threading/CMakeLists.windows-x86_64.txt index eedf3ebee2..c00337a5ca 100644 --- a/library/cpp/yt/threading/CMakeLists.windows-x86_64.txt +++ b/library/cpp/yt/threading/CMakeLists.windows-x86_64.txt @@ -28,6 +28,7 @@ target_sources(cpp-yt-threading PRIVATE ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/recursive_spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/rw_spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock_base.cpp + ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock_count.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_lock.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_wait.cpp ${CMAKE_SOURCE_DIR}/library/cpp/yt/threading/spin_wait_hook.cpp diff --git a/library/cpp/yt/threading/recursive_spin_lock-inl.h b/library/cpp/yt/threading/recursive_spin_lock-inl.h index ab829255d0..aca27ba1cf 100644 --- a/library/cpp/yt/threading/recursive_spin_lock-inl.h +++ b/library/cpp/yt/threading/recursive_spin_lock-inl.h @@ -30,7 +30,10 @@ inline bool TRecursiveSpinLock::TryAcquire() noexcept return false; } auto newValue = (oldRecursionDepth + 1) | (static_cast<TValue>(currentThreadId) << ThreadIdShift); - return Value_.compare_exchange_weak(oldValue, newValue); + + bool acquired = Value_.compare_exchange_weak(oldValue, newValue); + NDetail::RecordSpinLockAcquired(acquired); + return acquired; } inline void TRecursiveSpinLock::Release() noexcept @@ -41,6 +44,7 @@ inline void TRecursiveSpinLock::Release() noexcept YT_ASSERT((value >> ThreadIdShift) == GetSequentialThreadId()); #endif --Value_; + NDetail::RecordSpinLockReleased(); } inline bool TRecursiveSpinLock::IsLocked() const noexcept diff --git a/library/cpp/yt/threading/recursive_spin_lock.h b/library/cpp/yt/threading/recursive_spin_lock.h index 59a39d9f8f..87df7166a5 100644 --- a/library/cpp/yt/threading/recursive_spin_lock.h +++ b/library/cpp/yt/threading/recursive_spin_lock.h @@ -2,6 +2,7 @@ #include "public.h" #include "spin_lock_base.h" +#include "spin_lock_count.h" #include <library/cpp/yt/system/thread_id.h> @@ -44,6 +45,8 @@ private: void AcquireSlow() noexcept; }; +REGISTER_TRACKED_SPIN_LOCK_CLASS(TRecursiveSpinLock) + //////////////////////////////////////////////////////////////////////////////// } // namespace NYT::NThreading diff --git a/library/cpp/yt/threading/rw_spin_lock-inl.h b/library/cpp/yt/threading/rw_spin_lock-inl.h index 173059757c..779de1b64a 100644 --- a/library/cpp/yt/threading/rw_spin_lock-inl.h +++ b/library/cpp/yt/threading/rw_spin_lock-inl.h @@ -32,6 +32,7 @@ inline void TReaderWriterSpinLock::ReleaseReader() noexcept { auto prevValue = Value_.fetch_sub(ReaderDelta, std::memory_order::release); Y_ASSERT((prevValue & ~WriterMask) != 0); + NDetail::RecordSpinLockReleased(); } inline void TReaderWriterSpinLock::AcquireWriter() noexcept @@ -46,6 +47,7 @@ inline void TReaderWriterSpinLock::ReleaseWriter() noexcept { auto prevValue = Value_.fetch_and(~WriterMask, std::memory_order::release); Y_ASSERT(prevValue & WriterMask); + NDetail::RecordSpinLockReleased(); } inline bool TReaderWriterSpinLock::IsLocked() const noexcept @@ -70,6 +72,7 @@ inline bool TReaderWriterSpinLock::TryAcquireReader() noexcept Value_.fetch_sub(ReaderDelta, std::memory_order::relaxed); return false; } + NDetail::RecordSpinLockAcquired(); return true; } @@ -89,13 +92,19 @@ inline bool TReaderWriterSpinLock::TryAcquireReaderForkFriendly() noexcept return false; } auto newValue = oldValue + ReaderDelta; - return Value_.compare_exchange_weak(oldValue, newValue, std::memory_order::acquire); + + bool acquired = Value_.compare_exchange_weak(oldValue, newValue, std::memory_order::acquire); + NDetail::RecordSpinLockAcquired(acquired); + return acquired; } inline bool TReaderWriterSpinLock::TryAcquireWriter() noexcept { auto expected = UnlockedValue; - return Value_.compare_exchange_weak(expected, WriterMask, std::memory_order::acquire); + + bool acquired = Value_.compare_exchange_weak(expected, WriterMask, std::memory_order::acquire); + NDetail::RecordSpinLockAcquired(acquired); + return acquired; } inline bool TReaderWriterSpinLock::TryAndTryAcquireWriter() noexcept diff --git a/library/cpp/yt/threading/rw_spin_lock.h b/library/cpp/yt/threading/rw_spin_lock.h index d1235dfc4a..a915e677e8 100644 --- a/library/cpp/yt/threading/rw_spin_lock.h +++ b/library/cpp/yt/threading/rw_spin_lock.h @@ -2,6 +2,7 @@ #include "public.h" #include "spin_lock_base.h" +#include "spin_lock_count.h" #include <library/cpp/yt/memory/public.h> @@ -106,16 +107,16 @@ private: void AcquireWriterSlow() noexcept; }; +REGISTER_TRACKED_SPIN_LOCK_CLASS(TReaderWriterSpinLock) + //////////////////////////////////////////////////////////////////////////////// -//! A variant of TReaderWriterSpinLock occupyig the whole cache line. -class TPaddedReaderWriterSpinLock +//! A variant of TReaderWriterSpinLock occupying the whole cache line. +class alignas(CacheLineSize) TPaddedReaderWriterSpinLock : public TReaderWriterSpinLock -{ -private: - [[maybe_unused]] - char Padding_[CacheLineSize - sizeof(TReaderWriterSpinLock)]; -}; +{ }; + +REGISTER_TRACKED_SPIN_LOCK_CLASS(TPaddedReaderWriterSpinLock) //////////////////////////////////////////////////////////////////////////////// @@ -133,7 +134,6 @@ struct TForkFriendlyReaderSpinlockTraits static void Release(T* spinlock); }; - template <class T> struct TWriterSpinlockTraits { diff --git a/library/cpp/yt/threading/spin_lock-inl.h b/library/cpp/yt/threading/spin_lock-inl.h index 2e7b038eaf..b986c74e75 100644 --- a/library/cpp/yt/threading/spin_lock-inl.h +++ b/library/cpp/yt/threading/spin_lock-inl.h @@ -30,6 +30,7 @@ inline void TSpinLock::Release() noexcept #else YT_ASSERT(Value_.exchange(UnlockedValue, std::memory_order::release) != UnlockedValue); #endif + NDetail::RecordSpinLockReleased(); } inline bool TSpinLock::IsLocked() const noexcept @@ -45,11 +46,14 @@ inline bool TSpinLock::TryAcquire() noexcept #else auto newValue = LockedValue; #endif - return Value_.compare_exchange_weak( + + bool acquired = Value_.compare_exchange_weak( expectedValue, newValue, std::memory_order::acquire, std::memory_order::relaxed); + NDetail::RecordSpinLockAcquired(acquired); + return acquired; } inline bool TSpinLock::TryAndTryAcquire() noexcept diff --git a/library/cpp/yt/threading/spin_lock.h b/library/cpp/yt/threading/spin_lock.h index d0d5c3cdbf..b8277ebc8d 100644 --- a/library/cpp/yt/threading/spin_lock.h +++ b/library/cpp/yt/threading/spin_lock.h @@ -2,6 +2,7 @@ #include "public.h" #include "spin_lock_base.h" +#include "spin_lock_count.h" #include <library/cpp/yt/misc/port.h> @@ -62,16 +63,16 @@ private: void AcquireSlow() noexcept; }; +REGISTER_TRACKED_SPIN_LOCK_CLASS(TSpinLock) + //////////////////////////////////////////////////////////////////////////////// -//! A variant of TReaderWriterSpinLock occupyig the whole cache line. -class TPaddedSpinLock +//! A variant of TSpinLock occupying the whole cache line. +class alignas(CacheLineSize) TPaddedSpinLock : public TSpinLock -{ -private: - [[maybe_unused]] - char Padding_[CacheLineSize - sizeof(TSpinLock)]; -}; +{ }; + +REGISTER_TRACKED_SPIN_LOCK_CLASS(TPaddedSpinLock) //////////////////////////////////////////////////////////////////////////////// diff --git a/library/cpp/yt/threading/spin_lock_count-inl.h b/library/cpp/yt/threading/spin_lock_count-inl.h new file mode 100644 index 0000000000..196f833a87 --- /dev/null +++ b/library/cpp/yt/threading/spin_lock_count-inl.h @@ -0,0 +1,41 @@ +#pragma once +#ifndef SPIN_LOCK_COUNT_INL_H_ +#error "Direct inclusion of this file is not allowed, include spin_lock_count.h" +#endif +#undef SPIN_LOCK_COUNT_INL_H_ + +#include "public.h" +#include "spin_lock_base.h" + +#ifdef NDEBUG +#include <util/system/compiler.h> +#endif + +#include <cstdint> + +namespace NYT::NThreading::NPrivate { + +//////////////////////////////////////////////////////////////////////////////// + +#ifdef NDEBUG + +Y_FORCE_INLINE void RecordSpinLockAcquired([[maybe_unused]] bool isAcquired = true) +{ } + +Y_FORCE_INLINE void RecordSpinLockReleased() +{ } + +Y_FORCE_INLINE void VerifyNoSpinLockAffinity() +{ } + +#else + +void RecordSpinLockAcquired(bool isAcquired = true); +void RecordSpinLockReleased(); +void VerifyNoSpinLockAffinity(); + +#endif + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT::NThreading::NPrivate diff --git a/library/cpp/yt/threading/spin_lock_count.cpp b/library/cpp/yt/threading/spin_lock_count.cpp new file mode 100644 index 0000000000..501a8bd73e --- /dev/null +++ b/library/cpp/yt/threading/spin_lock_count.cpp @@ -0,0 +1,43 @@ + +#include "spin_lock_count.h" + +#include <library/cpp/yt/assert/assert.h> + +#include <library/cpp/yt/misc/tls.h> + +#include <util/system/types.h> + +namespace NYT::NThreading::NPrivate { + +#ifndef NDEBUG + +//////////////////////////////////////////////////////////////////////////////// + +YT_THREAD_LOCAL(i64) ActiveSpinLockCount = 0; + +//////////////////////////////////////////////////////////////////////////////// + +void RecordSpinLockAcquired(bool isAcquired) +{ + if (isAcquired) { + ActiveSpinLockCount++; + } +} + +void RecordSpinLockReleased() +{ + YT_VERIFY(ActiveSpinLockCount > 0); + ActiveSpinLockCount--; +} + +void VerifyNoSpinLockAffinity() +{ + YT_VERIFY(ActiveSpinLockCount == 0); +} + +#endif + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT::NThreading::NPrivate + diff --git a/library/cpp/yt/threading/spin_lock_count.h b/library/cpp/yt/threading/spin_lock_count.h new file mode 100644 index 0000000000..3640f231b2 --- /dev/null +++ b/library/cpp/yt/threading/spin_lock_count.h @@ -0,0 +1,62 @@ +#pragma once + +#define SPIN_LOCK_COUNT_INL_H_ +#include "spin_lock_count-inl.h" +#undef SPIN_LOCK_COUNT_INL_H_ + +namespace NYT::NThreading { + +// Tracks the number of spinlocks currently held by the thread. +// Generally useful to ensure that we are not holding a spinlock +// in a given context. +// Tracking is only active in debug builds. + +//////////////////////////////////////////////////////////////////////////////// + +namespace NDetail { + +// In order to properly support tracking in your spinlock you have to do two steps: +// 1) Insert RecordSpinlockAcquired and RecordSpinlockReleased inside your +// (Try)Acquire and Release calls. +// 2) (Optional) Write REGISTER_TRACKED_SPIN_LOCK_CLASS(TSpinLock) for your spinlock +// so that you can use algorithms aware of spinlock tracking. + +using NPrivate::RecordSpinLockAcquired; +using NPrivate::RecordSpinLockReleased; + +template <class TSpinLock> +struct TIsTrackedSpinLock + : public std::false_type +{ }; + +#define REGISTER_TRACKED_SPIN_LOCK_CLASS(Name) \ + namespace NDetail { \ + \ + template <> \ + struct TIsTrackedSpinLock<Name> \ + : public std::true_type \ + { }; \ + \ + } \ + +} // namespace NDetail + +//////////////////////////////////////////////////////////////////////////////// + +template <class T> +concept CTrackedSpinLock = NDetail::TIsTrackedSpinLock<T>::value; +//! Semantic requirements: +//! 1) T must have a method successful call to which begins critical section (e.g. Acquire). +//! 2) T must have a method successful call to which ends critical section (e.g. Release). +//! In (1) and (2) "successful" is expected to have a definition given by T's author. +//! 3) Beggining of a critical section CS must be sequenced before RecordSpinlockAcquired(true) call. +//! 4) RecordSpinlockAcquired(true) call must be sequenced before RecordSpinlockReleased() call. +//! 5) RecordSpinlockReleased() must be sequenced before the ending of the CS. + +//////////////////////////////////////////////////////////////////////////////// + +using NPrivate::VerifyNoSpinLockAffinity; + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT::NThreading diff --git a/library/cpp/yt/threading/traceless_guard-inl.h b/library/cpp/yt/threading/traceless_guard-inl.h new file mode 100644 index 0000000000..e03d5196c4 --- /dev/null +++ b/library/cpp/yt/threading/traceless_guard-inl.h @@ -0,0 +1,115 @@ +#pragma once + +#ifndef TRACELESS_GUARD_INL_H_ +#error "Direct inclusion of this file is not allowed, include traceless_guard.h" +#endif +#undef TRACELESS_GUARD_INL_H_ + +#include "rw_spin_lock.h" +#include "spin_lock_count.h" + +#include <util/system/guard.h> + +#include <concepts> + +namespace NYT::NThreading::NPrivate { + +//////////////////////////////////////////////////////////////////////////////// + +#ifdef NDEBUG + +template <class T, class TOps = TCommonLockOps<T>> +using TTracelessGuard = TGuard<T, TOps>; + +template <class T, class TOps = TCommonLockOps<T>> +using TTracelessInverseGuard = TInverseGuard<T, TOps>; + +template <class T, class TOps = TTryLockOps<T>> +using TTracelessTryGuard = TTryGuard<T, TOps>; + +template <class T> +using TTracelessReaderGuard = TReaderGuard<T>; + +template <class T> +using TTracelessWriterGuard = TWriterGuard<T>; + +#else + +template <class TOps> +struct TTracelessOps + : public TOps +{ + template <class T> + static void Acquire(T* t) noexcept + { + TOps::Acquire(t); + NDetail::RecordSpinLockReleased(); + } + + template <class T> + static void Release(T* t) noexcept + { + NDetail::RecordSpinLockAcquired(); + TOps::Release(t); + } + + template <class T> + requires requires (T* t) { { TOps::TryAcquire(t) } -> std::same_as<bool>; } + static bool TryAcquire(T* t) noexcept + { + bool isAcquired = TOps::TryAcquire(t); + + if (isAcquired) { + NDetail::RecordSpinLockReleased(); + } + + return isAcquired; + } +}; + +template <CTrackedSpinLock T, class TOps = TCommonLockOps<T>> +using TTracelessGuard = TGuard<T, TTracelessOps<TOps>>; + +template <CTrackedSpinLock T, class TOps = TCommonLockOps<T>> +using TTracelessInverseGuard = TInverseGuard<T, TTracelessOps<TOps>>; + +template <CTrackedSpinLock T, class TOps = TTryLockOps<T>> +using TTracelessTryGuard = TTryGuard<T, TTracelessOps<TOps>>; + +template <CTrackedSpinLock T> +using TTracelessReaderGuard = TGuard<T, TTracelessOps<TReaderSpinlockTraits<T>>>; + +template <CTrackedSpinLock T> +using TTracelessWriterGuard = TGuard<T, TTracelessOps<TWriterSpinlockTraits<T>>>; + +#endif + +//////////////////////////////////////////////////////////////////////////////// + +template <CTrackedSpinLock T> +TTracelessGuard<T> TracelessGuard(const T& mutex) +{ + return {&mutex}; +} + +template <CTrackedSpinLock T> +TTracelessTryGuard<T> TracelessTryGuard(const T& mutex) +{ + return {&mutex}; +} + +template <CTrackedSpinLock T> +TTracelessReaderGuard<T> TracelessReaderGuard(const T& mutex) +{ + return {&mutex}; +} + +template <CTrackedSpinLock T> +TTracelessWriterGuard<T> TracelessWriterGuard(const T& mutex) +{ + return {&mutex}; +} + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT::NThreading::NPrivate diff --git a/library/cpp/yt/threading/traceless_guard.h b/library/cpp/yt/threading/traceless_guard.h new file mode 100644 index 0000000000..10ad0ded98 --- /dev/null +++ b/library/cpp/yt/threading/traceless_guard.h @@ -0,0 +1,29 @@ +#pragma once + +#define TRACELESS_GUARD_INL_H_ +#include "traceless_guard-inl.h" +#undef TRACELESS_GUARD_INL_H_ + +namespace NYT::NThreading { + +// This guards are zero-cost replacements for normal ones +// which allow user to avoid spinlocks being tracked. + +//////////////////////////////////////////////////////////////////////////////// + +using NPrivate::TTracelessGuard; +using NPrivate::TTracelessInverseGuard; +using NPrivate::TTracelessTryGuard; +using NPrivate::TTracelessReaderGuard; +using NPrivate::TTracelessWriterGuard; + +//////////////////////////////////////////////////////////////////////////////// + +using NPrivate::TracelessGuard; +using NPrivate::TracelessTryGuard; +using NPrivate::TracelessReaderGuard; +using NPrivate::TracelessWriterGuard; + +//////////////////////////////////////////////////////////////////////////////// + +} // namespace NYT::NThreading diff --git a/library/cpp/yt/threading/ya.make b/library/cpp/yt/threading/ya.make index 4f1d7fbdde..3b2cb13d4f 100644 --- a/library/cpp/yt/threading/ya.make +++ b/library/cpp/yt/threading/ya.make @@ -14,6 +14,7 @@ SRCS( recursive_spin_lock.cpp rw_spin_lock.cpp spin_lock_base.cpp + spin_lock_count.cpp spin_lock.cpp spin_wait.cpp spin_wait_hook.cpp diff --git a/yt/yt/core/concurrency/fiber_scheduler_thread.cpp b/yt/yt/core/concurrency/fiber_scheduler_thread.cpp index 60f0d81b8f..7fcb074e84 100644 --- a/yt/yt/core/concurrency/fiber_scheduler_thread.cpp +++ b/yt/yt/core/concurrency/fiber_scheduler_thread.cpp @@ -11,6 +11,8 @@ #include <yt/yt/core/misc/shutdown.h> #include <yt/yt/core/misc/singleton.h> +#include <library/cpp/yt/threading/spin_lock_count.h> + #include <yt/yt/core/tracing/trace_context.h> #include <library/cpp/yt/memory/memory_tag.h> @@ -948,6 +950,7 @@ void WaitUntilSet(TFuture<void> future, IInvokerPtr invoker) return; } + NThreading::VerifyNoSpinLockAffinity(); YT_VERIFY(invoker != GetSyncInvoker()); // Ensure canceler created. diff --git a/yt/yt/library/ytprof/http/handler.cpp b/yt/yt/library/ytprof/http/handler.cpp index 382ffc1fec..2dbc631957 100644 --- a/yt/yt/library/ytprof/http/handler.cpp +++ b/yt/yt/library/ytprof/http/handler.cpp @@ -18,6 +18,8 @@ #include <library/cpp/cgiparam/cgiparam.h> +#include <library/cpp/yt/threading/traceless_guard.h> + #include <util/system/mutex.h> namespace NYT::NYTProf { @@ -40,7 +42,8 @@ public: void HandleRequest(const IRequestPtr& req, const IResponseWriterPtr& rsp) override { try { - TTryGuard guard(Lock_); + auto guard = NThreading::TracelessTryGuard(Lock_); + if (!guard) { rsp->SetStatus(EStatusCode::TooManyRequests); WaitFor(rsp->WriteBody(TSharedRef::FromString("Profile fetch already running"))) |