Leaving this as a comment for easier discussion, but unrelated to this line
An alternative approach could be to just move the UniqueLock::Enter implementation to sync.cpp, removing the need for ContendedLock altogether. It would probably prevent this function from being inlined, but compared to the cost of acquiring a lock (happy path) the extra function call should be negligible?
<details>
<summary>git diff on 79467e3ec7</summary>
diff --git a/src/sync.cpp b/src/sync.cpp
index 0e5c623d21..c8b902945d 100644
--- a/src/sync.cpp
+++ b/src/sync.cpp
@@ -20,18 +20,19 @@
#include <utility>
#include <vector>
-#ifdef DEBUG_LOCKCONTENTION
-
-template <typename LockType>
-void ContendedLock(std::string_view name, std::string_view file, int nLine, LockType& lock)
+template <typename MutexType>
+void UniqueLock<MutexType>::Enter(const char* pszName, const char* pszFile, int nLine)
{
- 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<std::mutex>& lock);
-template void ContendedLock(std::string_view name, std::string_view file, int nLine, std::unique_lock<std::recursive_mutex>& lock);
-
+ 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
+ Base::lock();
+}
+template void UniqueLock<Mutex>::Enter(const char*, const char*, int);
+template void UniqueLock<RecursiveMutex>::Enter(const char*, const char*, int);
+template void UniqueLock<GlobalMutex>::Enter(const char*, const char*, int);
#ifdef DEBUG_LOCKORDER
//
diff --git a/src/sync.h b/src/sync.h
index 00fdaae942..93dfe59a1e 100644
--- a/src/sync.h
+++ b/src/sync.h
@@ -73,16 +73,6 @@ 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 <typename LockType>
-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.
@@ -153,17 +143,7 @@ class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock
private:
using Base = typename MutexType::unique_lock;
- void Enter(const char* pszName, const char* pszFile, int nLine)
- {
- EnterCritical(pszName, pszFile, nLine, Base::mutex());
-#ifdef DEBUG_LOCKCONTENTION
- if (!Base::try_lock()) {
- ContendedLock(pszName, pszFile, nLine, static_cast<Base&>(*this));
- }
-#else
- Base::lock();
-#endif
- }
+ void Enter(const char* pszName, const char* pszFile, int nLine);
bool TryEnter(const char* pszName, const char* pszFile, int nLine)
{
</details>