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 /library/cpp/yt/threading/spin_lock_count.h | |
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) Все эти действия имеют эффект только в дебаг сборке. В релизе вся эта диагностика стирается.
Diffstat (limited to 'library/cpp/yt/threading/spin_lock_count.h')
-rw-r--r-- | library/cpp/yt/threading/spin_lock_count.h | 62 |
1 files changed, 62 insertions, 0 deletions
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 |