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 <shared_mutex>
20 : #include <string>
21 : #include <thread>
22 :
23 : /////////////////////////////////////////////////
24 : // //
25 : // THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE //
26 : // //
27 : /////////////////////////////////////////////////
28 :
29 : /*
30 : RecursiveMutex mutex;
31 : std::recursive_mutex mutex;
32 :
33 : LOCK(mutex);
34 : std::unique_lock<std::recursive_mutex> criticalblock(mutex);
35 :
36 : LOCK2(mutex1, mutex2);
37 : std::unique_lock<std::recursive_mutex> criticalblock1(mutex1);
38 : std::unique_lock<std::recursive_mutex> criticalblock2(mutex2);
39 :
40 : TRY_LOCK(mutex, name);
41 : std::unique_lock<std::recursive_mutex> name(mutex, std::try_to_lock_t);
42 :
43 : ENTER_CRITICAL_SECTION(mutex); // no RAII
44 : mutex.lock();
45 :
46 : LEAVE_CRITICAL_SECTION(mutex); // no RAII
47 : mutex.unlock();
48 : */
49 :
50 : ///////////////////////////////
51 : // //
52 : // THE ACTUAL IMPLEMENTATION //
53 : // //
54 : ///////////////////////////////
55 :
56 : #ifdef DEBUG_LOCKORDER
57 : template <typename MutexType>
58 : void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false);
59 : void LeaveCritical();
60 : void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
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 AssertSharedLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) SHARED_LOCKS_REQUIRED(cs);
65 : template <typename MutexType>
66 : void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs);
67 : void DeleteLock(void* cs);
68 : bool LockStackEmpty();
69 :
70 : /**
71 : * Call abort() if a potential lock order deadlock bug is detected, instead of
72 : * just logging information and throwing a logic_error. Defaults to true, and
73 : * set to false in DEBUG_LOCKORDER unit tests.
74 : */
75 : extern bool g_debug_lockorder_abort;
76 : #else
77 : template <typename MutexType>
78 731321021 : inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}
79 730944241 : inline void LeaveCritical() {}
80 18191391 : inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
81 : template <typename MutexType>
82 1458941634 : inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
83 : template <typename MutexType>
84 71591 : inline void AssertSharedLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) SHARED_LOCKS_REQUIRED(cs) {};
85 : template <typename MutexType>
86 290856417 : void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}
87 5592212 : inline void DeleteLock(void* cs) {}
88 12 : inline bool LockStackEmpty() { return true; }
89 : #endif
90 :
91 : /**
92 : * Template mixin that adds -Wthread-safety locking annotations and lock order
93 : * checking to a subset of the mutex API.
94 : */
95 : template <typename PARENT>
96 : class LOCKABLE AnnotatedMixin : public PARENT
97 : {
98 : public:
99 11177157 : ~AnnotatedMixin() {
100 5592212 : DeleteLock((void*)this);
101 11177157 : }
102 :
103 508339 : void lock() EXCLUSIVE_LOCK_FUNCTION()
104 : {
105 508339 : PARENT::lock();
106 508339 : }
107 :
108 508339 : void unlock() UNLOCK_FUNCTION()
109 : {
110 508339 : PARENT::unlock();
111 508339 : }
112 :
113 200 : bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
114 : {
115 200 : return PARENT::try_lock();
116 : }
117 :
118 : using unique_lock = std::unique_lock<PARENT>;
119 : #ifdef __clang__
120 : //! For negative capabilities in the Clang Thread Safety Analysis.
121 : //! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction
122 : //! with the ! operator, to indicate that a mutex should not be held.
123 : const AnnotatedMixin& operator!() const { return *this; }
124 : #endif // __clang__
125 : };
126 :
127 : template <typename PARENT>
128 : class LOCKABLE SharedAnnotatedMixin : public AnnotatedMixin<PARENT>
129 : {
130 : public:
131 : bool try_shared_lock() SHARED_TRYLOCK_FUNCTION(true)
132 : {
133 : return PARENT::try_shared_lock();
134 : }
135 : void shared_lock() SHARED_LOCK_FUNCTION()
136 : {
137 : PARENT::shared_lock();
138 : }
139 : using SharedLock = std::shared_lock<PARENT>;
140 : };
141 :
142 : /**
143 : * Wrapped mutex: supports recursive locking, but no waiting
144 : * TODO: We should move away from using the recursive lock by default.
145 : */
146 : using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
147 :
148 : /** Wrapped mutex: supports waiting but not recursive locking */
149 : using Mutex = AnnotatedMixin<std::mutex>;
150 :
151 : /** Different type to mark Mutex at global scope
152 : *
153 : * Thread safety analysis can't handle negative assertions about mutexes
154 : * with global scope well, so mark them with a separate type, and
155 : * eventually move all the mutexes into classes so they are not globally
156 : * visible.
157 : *
158 : * See: https://github.com/bitcoin/bitcoin/pull/20272#issuecomment-720755781
159 : */
160 : class GlobalMutex : public Mutex { };
161 :
162 : /** Wrapped shared mutex: supports read locking via .shared_lock, exclusive locking via .lock;
163 : * does not support recursive locking */
164 : using SharedMutex = SharedAnnotatedMixin<std::shared_mutex>;
165 :
166 : #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
167 : #define AssertSharedLockHeld(cs) AssertSharedLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
168 :
169 259530814 : inline void AssertLockNotHeldInline(const char* name, const char* file, int line, Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) { AssertLockNotHeldInternal(name, file, line, cs); }
170 1521715 : inline void AssertLockNotHeldInline(const char* name, const char* file, int line, RecursiveMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
171 : inline void AssertLockNotHeldInline(const char* name, const char* file, int line, GlobalMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
172 29803912 : inline void AssertLockNotHeldInline(const char* name, const char* file, int line, SharedMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
173 : #define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
174 :
175 : /** Wrapper around std::unique_lock style lock for MutexType. */
176 : template <typename MutexType>
177 : class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock
178 : {
179 : private:
180 : using Base = typename MutexType::unique_lock;
181 :
182 552870450 : void Enter(const char* pszName, const char* pszFile, int nLine)
183 : {
184 552870450 : EnterCritical(pszName, pszFile, nLine, Base::mutex());
185 : #ifdef DEBUG_LOCKCONTENTION
186 : if (Base::try_lock()) return;
187 : LOG_TIME_MICROS_WITH_CATEGORY(strprintf("lock contention %s, %s:%d", pszName, pszFile, nLine), BCLog::LOCK);
188 : #endif
189 552870450 : Base::lock();
190 552870450 : }
191 :
192 169507 : bool TryEnter(const char* pszName, const char* pszFile, int nLine)
193 : {
194 169507 : EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);
195 169507 : if (Base::try_lock()) {
196 169391 : return true;
197 : }
198 116 : LeaveCritical();
199 116 : return false;
200 169507 : }
201 :
202 : public:
203 1105677761 : UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
204 552790659 : {
205 552887102 : if (fTry)
206 169507 : TryEnter(pszName, pszFile, nLine);
207 : else
208 552717595 : Enter(pszName, pszFile, nLine);
209 1105677761 : }
210 :
211 560376 : UniqueLock(MutexType* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
212 280188 : {
213 280188 : if (!pmutexIn) return;
214 :
215 280087 : *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);
216 280087 : if (fTry)
217 0 : TryEnter(pszName, pszFile, nLine);
218 : else
219 280087 : Enter(pszName, pszFile, nLine);
220 560376 : }
221 :
222 1141625305 : ~UniqueLock() UNLOCK_FUNCTION()
223 570818413 : {
224 570806892 : if (Base::owns_lock())
225 553185439 : LeaveCritical();
226 1141625309 : }
227 :
228 169507 : operator bool()
229 : {
230 169507 : return Base::owns_lock();
231 : }
232 :
233 : protected:
234 : // needed for reverse_lock
235 35365567 : UniqueLock() { }
236 :
237 : public:
238 : /**
239 : * An RAII-style reverse lock. Unlocks on construction and locks on destruction.
240 : */
241 : class reverse_lock {
242 : public:
243 35366025 : explicit reverse_lock(UniqueLock& _lock, const char* _guardname, const char* _file, int _line) : lock(_lock), file(_file), line(_line) {
244 17683240 : CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);
245 17682040 : lock.unlock();
246 17680839 : LeaveCritical();
247 17680839 : lock.swap(templock);
248 35366025 : }
249 :
250 35369015 : ~reverse_lock() {
251 17684485 : templock.swap(lock);
252 17684485 : EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());
253 17684485 : lock.lock();
254 35369015 : }
255 :
256 : private:
257 : reverse_lock(reverse_lock const&);
258 : reverse_lock& operator=(reverse_lock const&);
259 :
260 : UniqueLock& lock;
261 : UniqueLock templock;
262 : std::string lockname;
263 : const std::string file;
264 : const int line;
265 : };
266 : friend class reverse_lock;
267 : };
268 :
269 : template <typename Mutex, typename Base = typename Mutex::SharedLock>
270 : class SCOPED_LOCKABLE SharedLock : public Base
271 : {
272 : private:
273 160112387 : void SharedEnter(const char* pszName, const char* pszFile, int nLine)
274 : {
275 160112387 : EnterCritical(pszName, pszFile, nLine, Base::mutex());
276 : #ifdef DEBUG_LOCKCONTENTION
277 : if (Base::try_lock()) return;
278 : LOG_TIME_MICROS_WITH_CATEGORY(strprintf("lock contention %s, %s:%d", pszName, pszFile, nLine), BCLog::LOCK);
279 : #endif
280 160112387 : Base::lock();
281 160112387 : }
282 :
283 0 : bool TrySharedEnter(const char* pszName, const char* pszFile, int nLine)
284 : {
285 0 : EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);
286 0 : if (Base::try_lock()) {
287 0 : return true;
288 : }
289 0 : LeaveCritical();
290 0 : return false;
291 0 : }
292 :
293 : public:
294 320229078 : SharedLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) SHARED_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
295 160111584 : {
296 160117494 : if (fTry) {
297 0 : TrySharedEnter(pszName, pszFile, nLine);
298 0 : } else {
299 160117494 : SharedEnter(pszName, pszFile, nLine);
300 : }
301 320229078 : }
302 :
303 : SharedLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) SHARED_LOCK_FUNCTION(pmutexIn)
304 : {
305 : if (!pmutexIn) return;
306 :
307 : *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);
308 : if (fTry) {
309 : TrySharedEnter(pszName, pszFile, nLine);
310 : } else {
311 : SharedEnter(pszName, pszFile, nLine);
312 : }
313 : }
314 :
315 320229991 : ~SharedLock() UNLOCK_FUNCTION()
316 160115083 : {
317 160114908 : if (Base::owns_lock()) {
318 160115145 : LeaveCritical();
319 160115145 : }
320 320230465 : }
321 : };
322 :
323 : #define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock UNIQUE_NAME(revlock)(g, #g, __FILE__, __LINE__)
324 :
325 : template<typename MutexArg>
326 : using ReadLock = SharedLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
327 :
328 : // When locking a Mutex, require negative capability to ensure the lock
329 : // is not already held
330 531736172 : inline Mutex& MaybeCheckNotHeld(Mutex& cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
331 : inline Mutex* MaybeCheckNotHeld(Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
332 :
333 : // When locking a GlobalMutex or RecursiveMutex or SharedMutex, just check it is not
334 : // locked in the surrounding scope.
335 : template <typename MutexType>
336 292638542 : inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
337 : template <typename MutexType>
338 280188 : inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
339 :
340 : #define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
341 : #define READ_LOCK(cs) ReadLock<decltype(cs)> UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
342 : #define LOCK2(cs1, cs2) \
343 : UniqueLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \
344 : UniqueLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__)
345 : #define TRY_LOCK(cs, name) UniqueLock name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__, true)
346 : #define TRY_READ_LOCK(cs, name) ReadLock<decltype(cs)> name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__, true)
347 : #define WAIT_LOCK(cs, name) UniqueLock name(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
348 :
349 : #define ENTER_CRITICAL_SECTION(cs) \
350 : { \
351 : EnterCritical(#cs, __FILE__, __LINE__, &cs); \
352 : (cs).lock(); \
353 : }
354 :
355 : #define LEAVE_CRITICAL_SECTION(cs) \
356 : { \
357 : std::string lockname; \
358 : CheckLastCritical(reinterpret_cast<void*>(&cs), lockname, #cs, __FILE__, __LINE__); \
359 : (cs).unlock(); \
360 : LeaveCritical(); \
361 : }
362 :
363 : //! Run code while locking a mutex.
364 : //!
365 : //! Examples:
366 : //!
367 : //! WITH_LOCK(cs, shared_val = shared_val + 1);
368 : //!
369 : //! int val = WITH_LOCK(cs, return shared_val);
370 : //!
371 : //! Note:
372 : //!
373 : //! Since the return type deduction follows that of decltype(auto), while the
374 : //! deduced type of:
375 : //!
376 : //! WITH_LOCK(cs, return {int i = 1; return i;});
377 : //!
378 : //! is int, the deduced type of:
379 : //!
380 : //! WITH_LOCK(cs, return {int j = 1; return (j);});
381 : //!
382 : //! is &int, a reference to a local variable
383 : //!
384 : //! The above is detectable at compile-time with the -Wreturn-local-addr flag in
385 : //! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
386 : #define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
387 : #define WITH_READ_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { READ_LOCK(cs); code; }())
388 :
389 : /** An implementation of a semaphore.
390 : *
391 : * See https://en.wikipedia.org/wiki/Semaphore_(programming)
392 : */
393 : class CSemaphore
394 : {
395 : private:
396 : std::condition_variable condition;
397 : std::mutex mutex;
398 : int value;
399 :
400 : public:
401 11284 : explicit CSemaphore(int init) noexcept : value(init) {}
402 :
403 : // Disallow default construct, copy, move.
404 : CSemaphore() = delete;
405 : CSemaphore(const CSemaphore&) = delete;
406 : CSemaphore(CSemaphore&&) = delete;
407 : CSemaphore& operator=(const CSemaphore&) = delete;
408 : CSemaphore& operator=(CSemaphore&&) = delete;
409 :
410 113246 : void wait() noexcept
411 : {
412 113246 : std::unique_lock<std::mutex> lock(mutex);
413 226492 : condition.wait(lock, [&]() { return value >= 1; });
414 113246 : value--;
415 113246 : }
416 :
417 149 : bool try_wait() noexcept
418 : {
419 149 : std::lock_guard<std::mutex> lock(mutex);
420 149 : if (value < 1) {
421 0 : return false;
422 : }
423 149 : value--;
424 149 : return true;
425 149 : }
426 :
427 166971 : void post() noexcept
428 : {
429 : {
430 166971 : std::lock_guard<std::mutex> lock(mutex);
431 166971 : value++;
432 166971 : }
433 166971 : condition.notify_one();
434 166971 : }
435 : };
436 :
437 : /** RAII-style semaphore lock */
438 : class CSemaphoreGrant
439 : {
440 : private:
441 : CSemaphore* sem;
442 : bool fHaveGrant;
443 :
444 : public:
445 113245 : void Acquire() noexcept
446 : {
447 113245 : if (fHaveGrant) {
448 0 : return;
449 : }
450 113245 : sem->wait();
451 113245 : fHaveGrant = true;
452 113245 : }
453 :
454 138642 : void Release() noexcept
455 : {
456 138642 : if (!fHaveGrant) {
457 25247 : return;
458 : }
459 113395 : sem->post();
460 113395 : fHaveGrant = false;
461 138642 : }
462 :
463 149 : bool TryAcquire() noexcept
464 : {
465 149 : if (!fHaveGrant && sem->try_wait()) {
466 149 : fHaveGrant = true;
467 149 : }
468 149 : return fHaveGrant;
469 : }
470 :
471 : // Disallow copy.
472 : CSemaphoreGrant(const CSemaphoreGrant&) = delete;
473 : CSemaphoreGrant& operator=(const CSemaphoreGrant&) = delete;
474 :
475 : // Allow move.
476 24 : CSemaphoreGrant(CSemaphoreGrant&& other) noexcept
477 12 : {
478 12 : sem = other.sem;
479 12 : fHaveGrant = other.fHaveGrant;
480 12 : other.fHaveGrant = false;
481 12 : other.sem = nullptr;
482 24 : }
483 :
484 4790 : CSemaphoreGrant& operator=(CSemaphoreGrant&& other) noexcept
485 : {
486 4790 : Release();
487 4790 : sem = other.sem;
488 4790 : fHaveGrant = other.fHaveGrant;
489 4790 : other.fHaveGrant = false;
490 4790 : other.sem = nullptr;
491 4790 : return *this;
492 : }
493 :
494 31144 : CSemaphoreGrant() noexcept : sem(nullptr), fHaveGrant(false) {}
495 :
496 226789 : explicit CSemaphoreGrant(CSemaphore& sema, bool fTry = false) noexcept : sem(&sema), fHaveGrant(false)
497 113394 : {
498 113395 : if (fTry) {
499 149 : TryAcquire();
500 149 : } else {
501 113246 : Acquire();
502 : }
503 226789 : }
504 :
505 257960 : ~CSemaphoreGrant()
506 128980 : {
507 128980 : Release();
508 257960 : }
509 :
510 152 : explicit operator bool() const noexcept
511 : {
512 152 : return fHaveGrant;
513 : }
514 : };
515 :
516 : #endif // BITCOIN_SYNC_H
|