aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yt/threading/spin_lock_count.h
diff options
context:
space:
mode:
authorarkady-e1ppa <arkady-e1ppa@yandex-team.com>2023-11-16 17:24:02 +0300
committerarkady-e1ppa <arkady-e1ppa@yandex-team.com>2023-11-16 18:51:45 +0300
commit6b40f0f1060a3e9d54347e52c7dc8fb278e6e86b (patch)
treeda4c8447ff495a023682292e1ac90309312ddb8f /library/cpp/yt/threading/spin_lock_count.h
parent8f8023320207d4dfa6e9b6c595fe272382595cdd (diff)
downloadydb-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.h62
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