diff --git a/src/sync.cpp b/src/sync.cpp index e59f86b94fc..0e5c623d212 100644 --- a/src/sync.cpp +++ b/src/sync.cpp @@ -4,6 +4,7 @@ #include +#include #include #include #include @@ -19,6 +20,19 @@ #include #include +#ifdef DEBUG_LOCKCONTENTION + +template +void ContendedLock(std::string_view name, std::string_view file, int nLine, LockType& lock) +{ + LOG_TIME_MICROS_WITH_CATEGORY(strprintf("lock contention %s, %s:%d", name, file, nLine), BCLog::LOCK); + lock.lock(); +} +template void ContendedLock(std::string_view name, std::string_view file, int nLine, std::unique_lock& lock); +template void ContendedLock(std::string_view name, std::string_view file, int nLine, std::unique_lock& lock); + +#endif + #ifdef DEBUG_LOCKORDER // // Early deadlock detection. diff --git a/src/sync.h b/src/sync.h index 548b51d9d16..00fdaae942b 100644 --- a/src/sync.h +++ b/src/sync.h @@ -6,10 +6,6 @@ #ifndef BITCOIN_SYNC_H #define BITCOIN_SYNC_H -#ifdef DEBUG_LOCKCONTENTION -#include -#endif - #include // IWYU pragma: export #include @@ -77,6 +73,16 @@ inline void DeleteLock(void* cs) {} inline bool LockStackEmpty() { return true; } #endif +/* + * Called when a mutex fails to lock immediately because it is held by another + * thread, or spuriously. Responsible for locking the lock before returning. + */ +#ifdef DEBUG_LOCKCONTENTION + +template +void ContendedLock(std::string_view name, std::string_view file, int nLine, LockType& lock); +#endif + /** * Template mixin that adds -Wthread-safety locking annotations and lock order * checking to a subset of the mutex API. @@ -151,10 +157,12 @@ private: { EnterCritical(pszName, pszFile, nLine, Base::mutex()); #ifdef DEBUG_LOCKCONTENTION - if (Base::try_lock()) return; - LOG_TIME_MICROS_WITH_CATEGORY(strprintf("lock contention %s, %s:%d", pszName, pszFile, nLine), BCLog::LOCK); -#endif + if (!Base::try_lock()) { + ContendedLock(pszName, pszFile, nLine, static_cast(*this)); + } +#else Base::lock(); +#endif } bool TryEnter(const char* pszName, const char* pszFile, int nLine)