Bitcoin Core 29.99.0
P2P Digital Currency
sync.h
Go to the documentation of this file.
1// Copyright (c) 2009-2010 Satoshi Nakamoto
2// Copyright (c) 2009-2022 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> // IWYU pragma: export
15#include <util/macros.h>
16
17#include <condition_variable>
18#include <mutex>
19#include <string>
20#include <thread>
21
23// //
24// THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE //
25// //
27
28/*
29RecursiveMutex mutex;
30 std::recursive_mutex mutex;
31
32LOCK(mutex);
33 std::unique_lock<std::recursive_mutex> criticalblock(mutex);
34
35LOCK2(mutex1, mutex2);
36 std::unique_lock<std::recursive_mutex> criticalblock1(mutex1);
37 std::unique_lock<std::recursive_mutex> criticalblock2(mutex2);
38
39TRY_LOCK(mutex, name);
40 std::unique_lock<std::recursive_mutex> name(mutex, std::try_to_lock_t);
41
42ENTER_CRITICAL_SECTION(mutex); // no RAII
43 mutex.lock();
44
45LEAVE_CRITICAL_SECTION(mutex); // no RAII
46 mutex.unlock();
47 */
48
50// //
51// THE ACTUAL IMPLEMENTATION //
52// //
54
55#ifdef DEBUG_LOCKORDER
56template <typename MutexType>
57void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false);
58void LeaveCritical();
59void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
60template <typename MutexType>
61void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs);
62template <typename MutexType>
63void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs);
64void DeleteLock(void* cs);
65bool LockStackEmpty();
66
72extern bool g_debug_lockorder_abort;
73#else
74template <typename MutexType>
75inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}
76inline void LeaveCritical() {}
77inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
78template <typename MutexType>
79inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
80template <typename MutexType>
81void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}
82inline void DeleteLock(void* cs) {}
83inline bool LockStackEmpty() { return true; }
84#endif
85
90template <typename PARENT>
91class LOCKABLE AnnotatedMixin : public PARENT
92{
93public:
95 DeleteLock((void*)this);
96 }
97
99 {
100 PARENT::lock();
101 }
102
104 {
105 PARENT::unlock();
106 }
107
109 {
110 return PARENT::try_lock();
111 }
112
113 using unique_lock = std::unique_lock<PARENT>;
114#ifdef __clang__
118 const AnnotatedMixin& operator!() const { return *this; }
119#endif // __clang__
120};
121
127
130
140class GlobalMutex : public Mutex { };
141
142#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
143
144inline void AssertLockNotHeldInline(const char* name, const char* file, int line, Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) { AssertLockNotHeldInternal(name, file, line, cs); }
145inline void AssertLockNotHeldInline(const char* name, const char* file, int line, RecursiveMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
146inline void AssertLockNotHeldInline(const char* name, const char* file, int line, GlobalMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
147#define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
148
150template <typename MutexType>
151class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock
152{
153private:
154 using Base = typename MutexType::unique_lock;
155
156 void Enter(const char* pszName, const char* pszFile, int nLine)
157 {
158 EnterCritical(pszName, pszFile, nLine, Base::mutex());
159#ifdef DEBUG_LOCKCONTENTION
160 if (Base::try_lock()) return;
161 LOG_TIME_MICROS_WITH_CATEGORY(strprintf("lock contention %s, %s:%d", pszName, pszFile, nLine), BCLog::LOCK);
162#endif
163 Base::lock();
164 }
165
166 bool TryEnter(const char* pszName, const char* pszFile, int nLine)
167 {
168 EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);
169 if (Base::try_lock()) {
170 return true;
171 }
173 return false;
174 }
175
176public:
177 UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
178 {
179 if (fTry)
180 TryEnter(pszName, pszFile, nLine);
181 else
182 Enter(pszName, pszFile, nLine);
183 }
184
185 UniqueLock(MutexType* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
186 {
187 if (!pmutexIn) return;
188
189 *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);
190 if (fTry)
191 TryEnter(pszName, pszFile, nLine);
192 else
193 Enter(pszName, pszFile, nLine);
194 }
195
197 {
198 if (Base::owns_lock())
200 }
201
202 operator bool()
203 {
204 return Base::owns_lock();
205 }
206
207protected:
208 // needed for reverse_lock
209 UniqueLock() = default;
210
211public:
216 public:
217 explicit reverse_lock(UniqueLock& _lock, const char* _guardname, const char* _file, int _line) : lock(_lock), file(_file), line(_line) {
218 CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);
219 lock.unlock();
221 lock.swap(templock);
222 }
223
225 templock.swap(lock);
226 EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());
227 lock.lock();
228 }
229
230 private:
233
236 std::string lockname;
237 const std::string file;
238 const int line;
239 };
240 friend class reverse_lock;
241};
242
243#define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock UNIQUE_NAME(revlock)(g, #g, __FILE__, __LINE__)
244
245// When locking a Mutex, require negative capability to ensure the lock
246// is not already held
249
250// When locking a GlobalMutex or RecursiveMutex, just check it is not
251// locked in the surrounding scope.
252template <typename MutexType>
253inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
254template <typename MutexType>
255inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
256
257#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
258#define LOCK2(cs1, cs2) \
259 UniqueLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \
260 UniqueLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__)
261#define LOCK_ARGS(cs) MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__
262#define TRY_LOCK(cs, name) UniqueLock name(LOCK_ARGS(cs), true)
263#define WAIT_LOCK(cs, name) UniqueLock name(LOCK_ARGS(cs))
264
265#define ENTER_CRITICAL_SECTION(cs) \
266 { \
267 EnterCritical(#cs, __FILE__, __LINE__, &cs); \
268 (cs).lock(); \
269 }
270
271#define LEAVE_CRITICAL_SECTION(cs) \
272 { \
273 std::string lockname; \
274 CheckLastCritical((void*)(&cs), lockname, #cs, __FILE__, __LINE__); \
275 (cs).unlock(); \
276 LeaveCritical(); \
277 }
278
302#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
303
304#endif // BITCOIN_SYNC_H
Template mixin that adds -Wthread-safety locking annotations and lock order checking to a subset of t...
Definition: sync.h:92
~AnnotatedMixin()
Definition: sync.h:94
std::unique_lock< PARENT > unique_lock
Definition: sync.h:113
bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
Definition: sync.h:108
void unlock() UNLOCK_FUNCTION()
Definition: sync.h:103
void lock() EXCLUSIVE_LOCK_FUNCTION()
Definition: sync.h:98
(Un)serialize a number as raw byte or 2 hexadecimal chars.
Different type to mark Mutex at global scope.
Definition: sync.h:140
An RAII-style reverse lock.
Definition: sync.h:215
UniqueLock & lock
Definition: sync.h:234
const std::string file
Definition: sync.h:237
std::string lockname
Definition: sync.h:236
reverse_lock(reverse_lock const &)
reverse_lock(UniqueLock &_lock, const char *_guardname, const char *_file, int _line)
Definition: sync.h:217
reverse_lock & operator=(reverse_lock const &)
UniqueLock templock
Definition: sync.h:235
Wrapper around std::unique_lock style lock for MutexType.
Definition: sync.h:152
~UniqueLock() UNLOCK_FUNCTION()
Definition: sync.h:196
bool TryEnter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:166
void Enter(const char *pszName, const char *pszFile, int nLine)
Definition: sync.h:156
UniqueLock()=default
UniqueLock(MutexType &mutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false) EXCLUSIVE_LOCK_FUNCTION(mutexIn)
Definition: sync.h:177
UniqueLock(MutexType *pmutexIn, const char *pszName, const char *pszFile, int nLine, bool fTry=false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
Definition: sync.h:185
static void pool cs
const char * name
Definition: rest.cpp:49
void AssertLockHeldInternal(const char *pszName, const char *pszFile, int nLine, MutexType *cs) EXCLUSIVE_LOCKS_REQUIRED(cs)
Definition: sync.h:79
void AssertLockNotHeldInline(const char *name, const char *file, int line, Mutex *cs) EXCLUSIVE_LOCKS_REQUIRED(!cs)
Definition: sync.h:144
void EnterCritical(const char *pszName, const char *pszFile, int nLine, MutexType *cs, bool fTry=false)
Definition: sync.h:75
void DeleteLock(void *cs)
Definition: sync.h:82
#define LOCK(cs)
Definition: sync.h:257
void CheckLastCritical(void *cs, std::string &lockname, const char *guardname, const char *file, int line)
Definition: sync.h:77
void LeaveCritical()
Definition: sync.h:76
bool LockStackEmpty()
Definition: sync.h:83
Mutex & MaybeCheckNotHeld(Mutex &cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs)
Definition: sync.h:247
void AssertLockNotHeldInternal(const char *pszName, const char *pszFile, int nLine, MutexType *cs) LOCKS_EXCLUDED(cs)
Definition: sync.h:81
#define EXCLUSIVE_LOCKS_REQUIRED(...)
Definition: threadsafety.h:49
#define EXCLUSIVE_TRYLOCK_FUNCTION(...)
Definition: threadsafety.h:44
#define LOCKS_EXCLUDED(...)
Definition: threadsafety.h:48
#define EXCLUSIVE_LOCK_FUNCTION(...)
Definition: threadsafety.h:42
#define SCOPED_LOCKABLE
Definition: threadsafety.h:37
#define LOCKABLE
Definition: threadsafety.h:36
#define LOCK_RETURNED(x)
Definition: threadsafety.h:47
#define UNLOCK_FUNCTION(...)
Definition: threadsafety.h:46
#define LOG_TIME_MICROS_WITH_CATEGORY(end_msg, log_category)
Definition: timer.h:101
#define strprintf
Format arguments and return the string or write to given std::ostream (see tinyformat::format doc for...
Definition: tinyformat.h:1172