sync.h
1 // Copyright (c) 2009-2010 Satoshi Nakamoto 2 // Copyright (c) 2009-present The Bitcoin Core developers 3 // Distributed under the MIT software license, see the accompanying 4 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 6 #ifndef BITCOIN_SYNC_H 7 #define BITCOIN_SYNC_H 8 9 #ifdef DEBUG_LOCKCONTENTION 10 #include <logging/timer.h> 11 #endif 12 13 #include <threadsafety.h> // IWYU pragma: export 14 #include <util/macros.h> 15 16 #include <cassert> 17 #include <condition_variable> 18 #include <mutex> 19 #include <string> 20 #include <thread> 21 22 //////////////////////////////////////////////// 23 // // 24 // THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE // 25 // // 26 //////////////////////////////////////////////// 27 28 /* 29 RecursiveMutex mutex; 30 std::recursive_mutex mutex; 31 32 LOCK(mutex); 33 std::unique_lock<std::recursive_mutex> criticalblock(mutex); 34 35 LOCK2(mutex1, mutex2); 36 std::unique_lock<std::recursive_mutex> criticalblock1(mutex1); 37 std::unique_lock<std::recursive_mutex> criticalblock2(mutex2); 38 39 TRY_LOCK(mutex, name); 40 std::unique_lock<std::recursive_mutex> name(mutex, std::try_to_lock_t); 41 */ 42 43 /////////////////////////////// 44 // // 45 // THE ACTUAL IMPLEMENTATION // 46 // // 47 /////////////////////////////// 48 49 #ifdef DEBUG_LOCKORDER 50 template <typename MutexType> 51 void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false); 52 void LeaveCritical(); 53 void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line); 54 template <typename MutexType> 55 void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs); 56 template <typename MutexType> 57 void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs); 58 void DeleteLock(void* cs); 59 bool LockStackEmpty(); 60 61 /** 62 * Call abort() if a potential lock order deadlock bug is detected, instead of 63 * just logging information and throwing a logic_error. Defaults to true, and 64 * set to false in DEBUG_LOCKORDER unit tests. 65 */ 66 extern bool g_debug_lockorder_abort; 67 #else 68 template <typename MutexType> 69 inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {} 70 inline void LeaveCritical() {} 71 inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {} 72 template <typename MutexType> 73 inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {} 74 template <typename MutexType> 75 void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {} 76 inline void DeleteLock(void* cs) {} 77 inline bool LockStackEmpty() { return true; } 78 #endif 79 80 /** 81 * Template mixin that adds -Wthread-safety locking annotations and lock order 82 * checking to a subset of the mutex API. 83 */ 84 template <typename PARENT> 85 class LOCKABLE AnnotatedMixin : public PARENT 86 { 87 public: 88 ~AnnotatedMixin() { 89 DeleteLock((void*)this); 90 } 91 92 void lock() EXCLUSIVE_LOCK_FUNCTION() 93 { 94 PARENT::lock(); 95 } 96 97 void unlock() UNLOCK_FUNCTION() 98 { 99 PARENT::unlock(); 100 } 101 102 bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true) 103 { 104 return PARENT::try_lock(); 105 } 106 107 using unique_lock = std::unique_lock<PARENT>; 108 #ifdef __clang__ 109 //! For negative capabilities in the Clang Thread Safety Analysis. 110 //! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction 111 //! with the ! operator, to indicate that a mutex should not be held. 112 const AnnotatedMixin& operator!() const { return *this; } 113 #endif // __clang__ 114 }; 115 116 /** 117 * Wrapped mutex: supports recursive locking, but no waiting 118 * TODO: We should move away from using the recursive lock by default. 119 */ 120 using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>; 121 122 /** Wrapped mutex: supports waiting but not recursive locking */ 123 using Mutex = AnnotatedMixin<std::mutex>; 124 125 /** Different type to mark Mutex at global scope 126 * 127 * Thread safety analysis can't handle negative assertions about mutexes 128 * with global scope well, so mark them with a separate type, and 129 * eventually move all the mutexes into classes so they are not globally 130 * visible. 131 * 132 * See: https://github.com/bitcoin/bitcoin/pull/20272#issuecomment-720755781 133 */ 134 class GlobalMutex : public Mutex { }; 135 136 #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs) 137 138 inline void AssertLockNotHeldInline(const char* name, const char* file, int line, Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) { AssertLockNotHeldInternal(name, file, line, cs); } 139 inline void AssertLockNotHeldInline(const char* name, const char* file, int line, RecursiveMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); } 140 inline void AssertLockNotHeldInline(const char* name, const char* file, int line, GlobalMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); } 141 #define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs) 142 143 /** Wrapper around std::unique_lock style lock for MutexType. */ 144 template <typename MutexType> 145 class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock 146 { 147 private: 148 using Base = typename MutexType::unique_lock; 149 150 void Enter(const char* pszName, const char* pszFile, int nLine) 151 { 152 EnterCritical(pszName, pszFile, nLine, Base::mutex()); 153 #ifdef DEBUG_LOCKCONTENTION 154 if (Base::try_lock()) return; 155 LOG_TIME_MICROS_WITH_CATEGORY(strprintf("lock contention %s, %s:%d", pszName, pszFile, nLine), BCLog::LOCK); 156 #endif 157 Base::lock(); 158 } 159 160 bool TryEnter(const char* pszName, const char* pszFile, int nLine) 161 { 162 EnterCritical(pszName, pszFile, nLine, Base::mutex(), true); 163 if (Base::try_lock()) { 164 return true; 165 } 166 LeaveCritical(); 167 return false; 168 } 169 170 public: 171 UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock) 172 { 173 if (fTry) 174 TryEnter(pszName, pszFile, nLine); 175 else 176 Enter(pszName, pszFile, nLine); 177 } 178 179 UniqueLock(MutexType* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn) 180 { 181 if (!pmutexIn) return; 182 183 *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock); 184 if (fTry) 185 TryEnter(pszName, pszFile, nLine); 186 else 187 Enter(pszName, pszFile, nLine); 188 } 189 190 ~UniqueLock() UNLOCK_FUNCTION() 191 { 192 if (Base::owns_lock()) 193 LeaveCritical(); 194 } 195 196 operator bool() 197 { 198 return Base::owns_lock(); 199 } 200 201 protected: 202 // needed for reverse_lock 203 UniqueLock() = default; 204 205 public: 206 /** 207 * An RAII-style reverse lock. Unlocks on construction and locks on destruction. 208 */ 209 class SCOPED_LOCKABLE reverse_lock { 210 public: 211 explicit reverse_lock(UniqueLock& _lock, const MutexType& mutex, const char* _guardname, const char* _file, int _line) UNLOCK_FUNCTION(mutex) : lock(_lock), file(_file), line(_line) { 212 // Ensure that mutex passed back for thread-safety analysis is indeed the original 213 assert(std::addressof(mutex) == lock.mutex()); 214 215 CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line); 216 lock.unlock(); 217 LeaveCritical(); 218 lock.swap(templock); 219 } 220 221 ~reverse_lock() UNLOCK_FUNCTION() { 222 templock.swap(lock); 223 EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex()); 224 lock.lock(); 225 } 226 227 private: 228 reverse_lock(reverse_lock const&); 229 reverse_lock& operator=(reverse_lock const&); 230 231 UniqueLock& lock; 232 UniqueLock templock; 233 std::string lockname; 234 const std::string file; 235 const int line; 236 }; 237 friend class reverse_lock; 238 }; 239 240 // clang's thread-safety analyzer is unable to deal with aliases of mutexes, so 241 // it is not possible to use the lock's copy of the mutex for that purpose. 242 // Instead, the original mutex needs to be passed back to the reverse_lock for 243 // the sake of thread-safety analysis, but it is not actually used otherwise. 244 #define REVERSE_LOCK(g, cs) typename std::decay<decltype(g)>::type::reverse_lock UNIQUE_NAME(revlock)(g, cs, #cs, __FILE__, __LINE__) 245 246 // When locking a Mutex, require negative capability to ensure the lock 247 // is not already held 248 inline Mutex& MaybeCheckNotHeld(Mutex& cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; } 249 inline Mutex* MaybeCheckNotHeld(Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; } 250 251 // When locking a GlobalMutex or RecursiveMutex, just check it is not 252 // locked in the surrounding scope. 253 template <typename MutexType> 254 inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; } 255 template <typename MutexType> 256 inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; } 257 258 #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__) 259 #define LOCK2(cs1, cs2) \ 260 UniqueLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \ 261 UniqueLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__) 262 #define LOCK_ARGS(cs) MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__ 263 #define TRY_LOCK(cs, name) UniqueLock name(LOCK_ARGS(cs), true) 264 #define WAIT_LOCK(cs, name) UniqueLock name(LOCK_ARGS(cs)) 265 266 //! Run code while locking a mutex. 267 //! 268 //! Examples: 269 //! 270 //! WITH_LOCK(cs, shared_val = shared_val + 1); 271 //! 272 //! int val = WITH_LOCK(cs, return shared_val); 273 //! 274 //! Note: 275 //! 276 //! Since the return type deduction follows that of decltype(auto), while the 277 //! deduced type of: 278 //! 279 //! WITH_LOCK(cs, int i = 1; return i); 280 //! 281 //! is int, the deduced type of: 282 //! 283 //! WITH_LOCK(cs, int j = 1; return (j)); 284 //! 285 //! is &int, a reference to a local variable 286 //! 287 //! The above is detectable at compile-time with the -Wreturn-local-addr flag in 288 //! gcc and the -Wreturn-stack-address flag in clang, both enabled by default. 289 #define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }()) 290 291 #endif // BITCOIN_SYNC_H