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