Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2021 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.h>
# 11 : : #include <logging/timer.h>
# 12 : : #endif
# 13 : :
# 14 : : #include <threadsafety.h>
# 15 : : #include <util/macros.h>
# 16 : :
# 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 : : ENTER_CRITICAL_SECTION(mutex); // no RAII
# 43 : : mutex.lock();
# 44 : :
# 45 : : LEAVE_CRITICAL_SECTION(mutex); // no RAII
# 46 : : mutex.unlock();
# 47 : : */
# 48 : :
# 49 : : ///////////////////////////////
# 50 : : // //
# 51 : : // THE ACTUAL IMPLEMENTATION //
# 52 : : // //
# 53 : : ///////////////////////////////
# 54 : :
# 55 : : #ifdef DEBUG_LOCKORDER
# 56 : : template <typename MutexType>
# 57 : : void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false);
# 58 : : void LeaveCritical();
# 59 : : void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
# 60 : : std::string LocksHeld();
# 61 : : template <typename MutexType>
# 62 : : void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs);
# 63 : : template <typename MutexType>
# 64 : : void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs);
# 65 : : void DeleteLock(void* cs);
# 66 : : bool LockStackEmpty();
# 67 : :
# 68 : : /**
# 69 : : * Call abort() if a potential lock order deadlock bug is detected, instead of
# 70 : : * just logging information and throwing a logic_error. Defaults to true, and
# 71 : : * set to false in DEBUG_LOCKORDER unit tests.
# 72 : : */
# 73 : : extern bool g_debug_lockorder_abort;
# 74 : : #else
# 75 : : template <typename MutexType>
# 76 : : inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}
# 77 : : inline void LeaveCritical() {}
# 78 : : inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
# 79 : : template <typename MutexType>
# 80 : : inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
# 81 : : template <typename MutexType>
# 82 : : void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}
# 83 : : inline void DeleteLock(void* cs) {}
# 84 : : inline bool LockStackEmpty() { return true; }
# 85 : : #endif
# 86 : 376690711 : #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
# 87 : 407329 : #define AssertLockNotHeld(cs) AssertLockNotHeldInternal(#cs, __FILE__, __LINE__, &cs)
# 88 : :
# 89 : : /**
# 90 : : * Template mixin that adds -Wthread-safety locking annotations and lock order
# 91 : : * checking to a subset of the mutex API.
# 92 : : */
# 93 : : template <typename PARENT>
# 94 : : class LOCKABLE AnnotatedMixin : public PARENT
# 95 : : {
# 96 : : public:
# 97 : 104672 : ~AnnotatedMixin() {
# 98 : 104672 : DeleteLock((void*)this);
# 99 : 104672 : }
# 100 : :
# 101 : : void lock() EXCLUSIVE_LOCK_FUNCTION()
# 102 : 89496 : {
# 103 : 89496 : PARENT::lock();
# 104 : 89496 : }
# 105 : :
# 106 : : void unlock() UNLOCK_FUNCTION()
# 107 : 89496 : {
# 108 : 89496 : PARENT::unlock();
# 109 : 89496 : }
# 110 : :
# 111 : : bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
# 112 : 400 : {
# 113 : 400 : return PARENT::try_lock();
# 114 : 400 : }
# 115 : :
# 116 : : using UniqueLock = std::unique_lock<PARENT>;
# 117 : : #ifdef __clang__
# 118 : : //! For negative capabilities in the Clang Thread Safety Analysis.
# 119 : : //! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction
# 120 : : //! with the ! operator, to indicate that a mutex should not be held.
# 121 : : const AnnotatedMixin& operator!() const { return *this; }
# 122 : : #endif // __clang__
# 123 : : };
# 124 : :
# 125 : : /**
# 126 : : * Wrapped mutex: supports recursive locking, but no waiting
# 127 : : * TODO: We should move away from using the recursive lock by default.
# 128 : : */
# 129 : : using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
# 130 : :
# 131 : : /** Wrapped mutex: supports waiting but not recursive locking */
# 132 : : typedef AnnotatedMixin<std::mutex> Mutex;
# 133 : :
# 134 : : /** Wrapper around std::unique_lock style lock for Mutex. */
# 135 : : template <typename Mutex, typename Base = typename Mutex::UniqueLock>
# 136 : : class SCOPED_LOCKABLE UniqueLock : public Base
# 137 : : {
# 138 : : private:
# 139 : : void Enter(const char* pszName, const char* pszFile, int nLine)
# 140 : 674281080 : {
# 141 : 674281080 : EnterCritical(pszName, pszFile, nLine, Base::mutex());
# 142 : : #ifdef DEBUG_LOCKCONTENTION
# 143 : : if (Base::try_lock()) return;
# 144 : : LOG_TIME_MICROS_WITH_CATEGORY(strprintf("lock contention %s, %s:%d", pszName, pszFile, nLine), BCLog::LOCK);
# 145 : : #endif
# 146 : 674281080 : Base::lock();
# 147 : 674281080 : }
# 148 : :
# 149 : : bool TryEnter(const char* pszName, const char* pszFile, int nLine)
# 150 : 1186 : {
# 151 : 1186 : EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);
# 152 : 1186 : Base::try_lock();
# 153 [ + + ][ - + ]: 1186 : if (!Base::owns_lock()) {
# 154 : 11 : LeaveCritical();
# 155 : 11 : }
# 156 : 1186 : return Base::owns_lock();
# 157 : 1186 : }
# 158 : :
# 159 : : public:
# 160 : : UniqueLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
# 161 : 674199866 : {
# 162 [ + + ][ + + ]: 674199866 : if (fTry)
# 163 : 1186 : TryEnter(pszName, pszFile, nLine);
# 164 : 674198680 : else
# 165 : 674198680 : Enter(pszName, pszFile, nLine);
# 166 : 674199866 : }
# 167 : :
# 168 : : UniqueLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
# 169 : 83109 : {
# 170 [ + + ]: 83109 : if (!pmutexIn) return;
# 171 : :
# 172 : 83008 : *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);
# 173 [ - + ]: 83008 : if (fTry)
# 174 : 0 : TryEnter(pszName, pszFile, nLine);
# 175 : 83008 : else
# 176 : 83008 : Enter(pszName, pszFile, nLine);
# 177 : 83008 : }
# 178 : :
# 179 : : ~UniqueLock() UNLOCK_FUNCTION()
# 180 : 675029262 : {
# 181 [ + + ][ + + ]: 675029262 : if (Base::owns_lock())
# 182 : 674284103 : LeaveCritical();
# 183 : 675029262 : }
# 184 : :
# 185 : : operator bool()
# 186 : 1186 : {
# 187 : 1186 : return Base::owns_lock();
# 188 : 1186 : }
# 189 : :
# 190 : : protected:
# 191 : : // needed for reverse_lock
# 192 : 745001 : UniqueLock() { }
# 193 : :
# 194 : : public:
# 195 : : /**
# 196 : : * An RAII-style reverse lock. Unlocks on construction and locks on destruction.
# 197 : : */
# 198 : : class reverse_lock {
# 199 : : public:
# 200 : 745001 : explicit reverse_lock(UniqueLock& _lock, const char* _guardname, const char* _file, int _line) : lock(_lock), file(_file), line(_line) {
# 201 : 745001 : CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);
# 202 : 745001 : lock.unlock();
# 203 : 745001 : LeaveCritical();
# 204 : 745001 : lock.swap(templock);
# 205 : 745001 : }
# 206 : :
# 207 : 744996 : ~reverse_lock() {
# 208 : 744996 : templock.swap(lock);
# 209 : 744996 : EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());
# 210 : 744996 : lock.lock();
# 211 : 744996 : }
# 212 : :
# 213 : : private:
# 214 : : reverse_lock(reverse_lock const&);
# 215 : : reverse_lock& operator=(reverse_lock const&);
# 216 : :
# 217 : : UniqueLock& lock;
# 218 : : UniqueLock templock;
# 219 : : std::string lockname;
# 220 : : const std::string file;
# 221 : : const int line;
# 222 : : };
# 223 : : friend class reverse_lock;
# 224 : : };
# 225 : :
# 226 : 744999 : #define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock UNIQUE_NAME(revlock)(g, #g, __FILE__, __LINE__)
# 227 : :
# 228 : : template<typename MutexArg>
# 229 : : using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
# 230 : :
# 231 : 670264698 : #define LOCK(cs) DebugLock<decltype(cs)> UNIQUE_NAME(criticalblock)(cs, #cs, __FILE__, __LINE__)
# 232 : : #define LOCK2(cs1, cs2) \
# 233 : 378247 : DebugLock<decltype(cs1)> criticalblock1(cs1, #cs1, __FILE__, __LINE__); \
# 234 : 378247 : DebugLock<decltype(cs2)> criticalblock2(cs2, #cs2, __FILE__, __LINE__);
# 235 : 1186 : #define TRY_LOCK(cs, name) DebugLock<decltype(cs)> name(cs, #cs, __FILE__, __LINE__, true)
# 236 : 3252249 : #define WAIT_LOCK(cs, name) DebugLock<decltype(cs)> name(cs, #cs, __FILE__, __LINE__)
# 237 : :
# 238 : : #define ENTER_CRITICAL_SECTION(cs) \
# 239 : 89480 : { \
# 240 : 89480 : EnterCritical(#cs, __FILE__, __LINE__, &cs); \
# 241 : 89480 : (cs).lock(); \
# 242 : 89480 : }
# 243 : :
# 244 : : #define LEAVE_CRITICAL_SECTION(cs) \
# 245 : 89480 : { \
# 246 : 89480 : std::string lockname; \
# 247 : 89480 : CheckLastCritical((void*)(&cs), lockname, #cs, __FILE__, __LINE__); \
# 248 : 89480 : (cs).unlock(); \
# 249 : 89480 : LeaveCritical(); \
# 250 : 89480 : }
# 251 : :
# 252 : : //! Run code while locking a mutex.
# 253 : : //!
# 254 : : //! Examples:
# 255 : : //!
# 256 : : //! WITH_LOCK(cs, shared_val = shared_val + 1);
# 257 : : //!
# 258 : : //! int val = WITH_LOCK(cs, return shared_val);
# 259 : : //!
# 260 : : //! Note:
# 261 : : //!
# 262 : : //! Since the return type deduction follows that of decltype(auto), while the
# 263 : : //! deduced type of:
# 264 : : //!
# 265 : : //! WITH_LOCK(cs, return {int i = 1; return i;});
# 266 : : //!
# 267 : : //! is int, the deduced type of:
# 268 : : //!
# 269 : : //! WITH_LOCK(cs, return {int j = 1; return (j);});
# 270 : : //!
# 271 : : //! is &int, a reference to a local variable
# 272 : : //!
# 273 : : //! The above is detectable at compile-time with the -Wreturn-local-addr flag in
# 274 : : //! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
# 275 [ + + ][ + - ]: 289652 : #define WITH_LOCK(cs, code) [&]() -> decltype(auto) { LOCK(cs); code; }()
# [ + + ]
# 276 : :
# 277 : : class CSemaphore
# 278 : : {
# 279 : : private:
# 280 : : std::condition_variable condition;
# 281 : : std::mutex mutex;
# 282 : : int value;
# 283 : :
# 284 : : public:
# 285 : 1438 : explicit CSemaphore(int init) : value(init) {}
# 286 : :
# 287 : : void wait()
# 288 : 5825 : {
# 289 : 5825 : std::unique_lock<std::mutex> lock(mutex);
# 290 : 5825 : condition.wait(lock, [&]() { return value >= 1; });
# 291 : 5825 : value--;
# 292 : 5825 : }
# 293 : :
# 294 : : bool try_wait()
# 295 : 56 : {
# 296 : 56 : std::lock_guard<std::mutex> lock(mutex);
# 297 [ - + ]: 56 : if (value < 1)
# 298 : 0 : return false;
# 299 : 56 : value--;
# 300 : 56 : return true;
# 301 : 56 : }
# 302 : :
# 303 : : void post()
# 304 : 19535 : {
# 305 : 19535 : {
# 306 : 19535 : std::lock_guard<std::mutex> lock(mutex);
# 307 : 19535 : value++;
# 308 : 19535 : }
# 309 : 19535 : condition.notify_one();
# 310 : 19535 : }
# 311 : : };
# 312 : :
# 313 : : /** RAII-style semaphore lock */
# 314 : : class CSemaphoreGrant
# 315 : : {
# 316 : : private:
# 317 : : CSemaphore* sem;
# 318 : : bool fHaveGrant;
# 319 : :
# 320 : : public:
# 321 : : void Acquire()
# 322 : 5825 : {
# 323 [ - + ]: 5825 : if (fHaveGrant)
# 324 : 0 : return;
# 325 : 5825 : sem->wait();
# 326 : 5825 : fHaveGrant = true;
# 327 : 5825 : }
# 328 : :
# 329 : : void Release()
# 330 : 7509 : {
# 331 [ + + ]: 7509 : if (!fHaveGrant)
# 332 : 1628 : return;
# 333 : 5881 : sem->post();
# 334 : 5881 : fHaveGrant = false;
# 335 : 5881 : }
# 336 : :
# 337 : : bool TryAcquire()
# 338 : 58 : {
# 339 [ + + ][ + - ]: 58 : if (!fHaveGrant && sem->try_wait())
# 340 : 56 : fHaveGrant = true;
# 341 : 58 : return fHaveGrant;
# 342 : 58 : }
# 343 : :
# 344 : : void MoveTo(CSemaphoreGrant& grant)
# 345 : 55 : {
# 346 : 55 : grant.Release();
# 347 : 55 : grant.sem = sem;
# 348 : 55 : grant.fHaveGrant = fHaveGrant;
# 349 : 55 : fHaveGrant = false;
# 350 : 55 : }
# 351 : :
# 352 : 1157 : CSemaphoreGrant() : sem(nullptr), fHaveGrant(false) {}
# 353 : :
# 354 : : explicit CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false)
# 355 : 5881 : {
# 356 [ + + ]: 5881 : if (fTry)
# 357 : 56 : TryAcquire();
# 358 : 5825 : else
# 359 : 5825 : Acquire();
# 360 : 5881 : }
# 361 : :
# 362 : : ~CSemaphoreGrant()
# 363 : 7038 : {
# 364 : 7038 : Release();
# 365 : 7038 : }
# 366 : :
# 367 : : operator bool() const
# 368 : 56 : {
# 369 : 56 : return fHaveGrant;
# 370 : 56 : }
# 371 : : };
# 372 : :
# 373 : : #endif // BITCOIN_SYNC_H
|