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 : void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false);
52 : void LeaveCritical();
53 : void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
54 : std::string LocksHeld();
55 : template <typename MutexType>
56 : void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs);
57 : template <typename MutexType>
58 : void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs);
59 : void DeleteLock(void* cs);
60 : bool LockStackEmpty();
61 :
62 : /**
63 : * Call abort() if a potential lock order deadlock bug is detected, instead of
64 : * just logging information and throwing a logic_error. Defaults to true, and
65 : * set to false in DEBUG_LOCKORDER unit tests.
66 : */
67 : extern bool g_debug_lockorder_abort;
68 : #else
69 50465230 : inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, void* cs, bool fTry = false) {}
70 50467441 : inline void LeaveCritical() {}
71 658769 : inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
72 : template <typename MutexType>
73 12434498 : inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
74 : template <typename MutexType>
75 229143 : void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) {}
76 71546 : inline void DeleteLock(void* cs) {}
77 8 : inline bool LockStackEmpty() { return true; }
78 : #endif
79 : #define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
80 : #define AssertLockNotHeld(cs) AssertLockNotHeldInternal(#cs, __FILE__, __LINE__, &cs)
81 :
82 : /**
83 : * Template mixin that adds -Wthread-safety locking annotations and lock order
84 : * checking to a subset of the mutex API.
85 : */
86 : template <typename PARENT>
87 123176 : class LOCKABLE AnnotatedMixin : public PARENT
88 : {
89 : public:
90 143092 : ~AnnotatedMixin() {
91 71546 : DeleteLock((void*)this);
92 143092 : }
93 :
94 20 : void lock() EXCLUSIVE_LOCK_FUNCTION()
95 : {
96 20 : PARENT::lock();
97 20 : }
98 :
99 20 : void unlock() UNLOCK_FUNCTION()
100 : {
101 20 : PARENT::unlock();
102 20 : }
103 :
104 : bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
105 : {
106 : return PARENT::try_lock();
107 : }
108 :
109 : using UniqueLock = std::unique_lock<PARENT>;
110 : #ifdef __clang__
111 : //! For negative capabilities in the Clang Thread Safety Analysis.
112 : //! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction
113 : //! with the ! operator, to indicate that a mutex should not be held.
114 : const AnnotatedMixin& operator!() const { return *this; }
115 : #endif // __clang__
116 : };
117 :
118 : /**
119 : * Wrapped mutex: supports recursive locking, but no waiting
120 : * TODO: We should move away from using the recursive lock by default.
121 : */
122 : using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
123 :
124 : /** Wrapped mutex: supports waiting but not recursive locking */
125 : typedef AnnotatedMixin<std::mutex> Mutex;
126 :
127 : #ifdef DEBUG_LOCKCONTENTION
128 : void PrintLockContention(const char* pszName, const char* pszFile, int nLine);
129 : #endif
130 :
131 : /** Wrapper around std::unique_lock style lock for Mutex. */
132 : template <typename Mutex, typename Base = typename Mutex::UniqueLock>
133 : class SCOPED_LOCKABLE UniqueLock : public Base
134 : {
135 : private:
136 49742912 : void Enter(const char* pszName, const char* pszFile, int nLine)
137 : {
138 49742912 : EnterCritical(pszName, pszFile, nLine, (void*)(Base::mutex()));
139 : #ifdef DEBUG_LOCKCONTENTION
140 : if (!Base::try_lock()) {
141 : PrintLockContention(pszName, pszFile, nLine);
142 : #endif
143 49742912 : Base::lock();
144 : #ifdef DEBUG_LOCKCONTENTION
145 : }
146 : #endif
147 49742912 : }
148 :
149 1413 : bool TryEnter(const char* pszName, const char* pszFile, int nLine)
150 : {
151 1413 : EnterCritical(pszName, pszFile, nLine, (void*)(Base::mutex()), true);
152 1413 : Base::try_lock();
153 1413 : if (!Base::owns_lock())
154 25 : LeaveCritical();
155 1413 : return Base::owns_lock();
156 : }
157 :
158 : public:
159 99489280 : UniqueLock(Mutex& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
160 99489280 : {
161 49744484 : if (fTry)
162 1413 : TryEnter(pszName, pszFile, nLine);
163 : else
164 49742842 : Enter(pszName, pszFile, nLine);
165 99491592 : }
166 :
167 : UniqueLock(Mutex* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
168 : {
169 : if (!pmutexIn) return;
170 :
171 : *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);
172 : if (fTry)
173 : TryEnter(pszName, pszFile, nLine);
174 : else
175 : Enter(pszName, pszFile, nLine);
176 : }
177 :
178 100809843 : ~UniqueLock() UNLOCK_FUNCTION()
179 50404996 : {
180 50404847 : if (Base::owns_lock())
181 49746220 : LeaveCritical();
182 100809935 : }
183 :
184 1413 : operator bool()
185 : {
186 1413 : return Base::owns_lock();
187 : }
188 :
189 : protected:
190 : // needed for reverse_lock
191 1317538 : UniqueLock() { }
192 :
193 : public:
194 : /**
195 : * An RAII-style reverse lock. Unlocks on construction and locks on destruction.
196 : */
197 : class reverse_lock {
198 : public:
199 1317538 : explicit reverse_lock(UniqueLock& _lock, const char* _guardname, const char* _file, int _line) : lock(_lock), file(_file), line(_line) {
200 658769 : CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);
201 658769 : lock.unlock();
202 658768 : LeaveCritical();
203 658768 : lock.swap(templock);
204 1317538 : }
205 :
206 1317532 : ~reverse_lock() {
207 658766 : templock.swap(lock);
208 658766 : EnterCritical(lockname.c_str(), file.c_str(), line, (void*)lock.mutex());
209 658766 : lock.lock();
210 1317534 : }
211 :
212 : private:
213 : reverse_lock(reverse_lock const&);
214 : reverse_lock& operator=(reverse_lock const&);
215 :
216 : UniqueLock& lock;
217 : UniqueLock templock;
218 : std::string lockname;
219 : const std::string file;
220 : const int line;
221 : };
222 : friend class reverse_lock;
223 : };
224 :
225 : #define REVERSE_LOCK(g) typename std::decay<decltype(g)>::type::reverse_lock PASTE2(revlock, __COUNTER__)(g, #g, __FILE__, __LINE__)
226 :
227 : template<typename MutexArg>
228 : using DebugLock = UniqueLock<typename std::remove_reference<typename std::remove_pointer<MutexArg>::type>::type>;
229 :
230 : #define LOCK(cs) DebugLock<decltype(cs)> PASTE2(criticalblock, __COUNTER__)(cs, #cs, __FILE__, __LINE__)
231 : #define LOCK2(cs1, cs2) \
232 : DebugLock<decltype(cs1)> criticalblock1(cs1, #cs1, __FILE__, __LINE__); \
233 : DebugLock<decltype(cs2)> criticalblock2(cs2, #cs2, __FILE__, __LINE__);
234 : #define TRY_LOCK(cs, name) DebugLock<decltype(cs)> name(cs, #cs, __FILE__, __LINE__, true)
235 : #define WAIT_LOCK(cs, name) DebugLock<decltype(cs)> name(cs, #cs, __FILE__, __LINE__)
236 :
237 : #define ENTER_CRITICAL_SECTION(cs) \
238 : { \
239 : EnterCritical(#cs, __FILE__, __LINE__, (void*)(&cs)); \
240 : (cs).lock(); \
241 : }
242 :
243 : #define LEAVE_CRITICAL_SECTION(cs) \
244 : { \
245 : (cs).unlock(); \
246 : LeaveCritical(); \
247 : }
248 :
249 : //! Run code while locking a mutex.
250 : //!
251 : //! Examples:
252 : //!
253 : //! WITH_LOCK(cs, shared_val = shared_val + 1);
254 : //!
255 : //! int val = WITH_LOCK(cs, return shared_val);
256 : //!
257 : #define WITH_LOCK(cs, code) [&] { LOCK(cs); code; }()
258 :
259 1968 : class CSemaphore
260 : {
261 : private:
262 : std::condition_variable condition;
263 : std::mutex mutex;
264 : int value;
265 :
266 : public:
267 1968 : explicit CSemaphore(int init) : value(init) {}
268 :
269 32202 : void wait()
270 : {
271 32202 : std::unique_lock<std::mutex> lock(mutex);
272 64404 : condition.wait(lock, [&]() { return value >= 1; });
273 32202 : value--;
274 32202 : }
275 :
276 0 : bool try_wait()
277 : {
278 0 : std::lock_guard<std::mutex> lock(mutex);
279 0 : if (value < 1)
280 0 : return false;
281 0 : value--;
282 0 : return true;
283 0 : }
284 :
285 41549 : void post()
286 : {
287 : {
288 41549 : std::lock_guard<std::mutex> lock(mutex);
289 41549 : value++;
290 41549 : }
291 41549 : condition.notify_one();
292 41549 : }
293 : };
294 :
295 : /** RAII-style semaphore lock */
296 : class CSemaphoreGrant
297 : {
298 : private:
299 : CSemaphore* sem;
300 : bool fHaveGrant;
301 :
302 : public:
303 32202 : void Acquire()
304 : {
305 32202 : if (fHaveGrant)
306 : return;
307 32202 : sem->wait();
308 32202 : fHaveGrant = true;
309 32202 : }
310 :
311 33230 : void Release()
312 : {
313 33230 : if (!fHaveGrant)
314 : return;
315 32202 : sem->post();
316 32202 : fHaveGrant = false;
317 33230 : }
318 :
319 1 : bool TryAcquire()
320 : {
321 1 : if (!fHaveGrant && sem->try_wait())
322 0 : fHaveGrant = true;
323 1 : return fHaveGrant;
324 : }
325 :
326 0 : void MoveTo(CSemaphoreGrant& grant)
327 : {
328 0 : grant.Release();
329 0 : grant.sem = sem;
330 0 : grant.fHaveGrant = fHaveGrant;
331 0 : fHaveGrant = false;
332 0 : }
333 :
334 1458 : CSemaphoreGrant() : sem(nullptr), fHaveGrant(false) {}
335 :
336 64404 : explicit CSemaphoreGrant(CSemaphore& sema, bool fTry = false) : sem(&sema), fHaveGrant(false)
337 32202 : {
338 32202 : if (fTry)
339 0 : TryAcquire();
340 : else
341 32202 : Acquire();
342 64404 : }
343 :
344 65862 : ~CSemaphoreGrant()
345 32931 : {
346 32931 : Release();
347 65862 : }
348 :
349 0 : operator bool() const
350 : {
351 0 : return fHaveGrant;
352 : }
353 : };
354 :
355 : // Utility class for indicating to compiler thread analysis that a mutex is
356 : // locked (when it couldn't be determined otherwise).
357 : struct SCOPED_LOCKABLE LockAssertion
358 : {
359 : template <typename Mutex>
360 156776 : explicit LockAssertion(Mutex& mutex) EXCLUSIVE_LOCK_FUNCTION(mutex)
361 78388 : {
362 : #ifdef DEBUG_LOCKORDER
363 : AssertLockHeld(mutex);
364 : #endif
365 156776 : }
366 156776 : ~LockAssertion() UNLOCK_FUNCTION() {}
367 : };
368 :
369 : #endif // BITCOIN_SYNC_H
|