Coverage Report

Created: 2025-06-10 13:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/sync.h
Line
Count
Source
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
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
template <typename MutexType>
61
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs);
62
template <typename MutexType>
63
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs);
64
void DeleteLock(void* cs);
65
bool LockStackEmpty();
66
67
/**
68
 * Call abort() if a potential lock order deadlock bug is detected, instead of
69
 * just logging information and throwing a logic_error. Defaults to true, and
70
 * set to false in DEBUG_LOCKORDER unit tests.
71
 */
72
extern bool g_debug_lockorder_abort;
73
#else
74
template <typename MutexType>
75
2.36G
inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}
void EnterCritical<std::recursive_mutex>(char const*, char const*, int, std::recursive_mutex*, bool)
Line
Count
Source
75
1.13G
inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}
void EnterCritical<std::mutex>(char const*, char const*, int, std::mutex*, bool)
Line
Count
Source
75
1.22G
inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}
Unexecuted instantiation: void EnterCritical<AnnotatedMixin<std::recursive_mutex> >(char const*, char const*, int, AnnotatedMixin<std::recursive_mutex>*, bool)
76
2.35G
inline void LeaveCritical() {}
77
61.1M
inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
78
template <typename MutexType>
79
402M
inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
void AssertLockHeldInternal<AnnotatedMixin<std::mutex> >(char const*, char const*, int, AnnotatedMixin<std::mutex>*)
Line
Count
Source
79
196M
inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
void AssertLockHeldInternal<AnnotatedMixin<std::recursive_mutex> >(char const*, char const*, int, AnnotatedMixin<std::recursive_mutex>*)
Line
Count
Source
79
206M
inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
80
template <typename MutexType>
81
441M
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}
void AssertLockNotHeldInternal<AnnotatedMixin<std::mutex> >(char const*, char const*, int, AnnotatedMixin<std::mutex>*)
Line
Count
Source
81
425M
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}
void AssertLockNotHeldInternal<AnnotatedMixin<std::recursive_mutex> >(char const*, char const*, int, AnnotatedMixin<std::recursive_mutex>*)
Line
Count
Source
81
15.9M
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}
Unexecuted instantiation: void AssertLockNotHeldInternal<GlobalMutex>(char const*, char const*, int, GlobalMutex*)
82
2.06M
inline void DeleteLock(void* cs) {}
83
0
inline bool LockStackEmpty() { return true; }
84
#endif
85
86
/**
87
 * Template mixin that adds -Wthread-safety locking annotations and lock order
88
 * checking to a subset of the mutex API.
89
 */
90
template <typename PARENT>
91
class LOCKABLE AnnotatedMixin : public PARENT
92
{
93
public:
94
2.06M
    ~AnnotatedMixin() {
95
2.06M
        DeleteLock((void*)this);
96
2.06M
    }
AnnotatedMixin<std::mutex>::~AnnotatedMixin()
Line
Count
Source
94
1.74M
    ~AnnotatedMixin() {
95
1.74M
        DeleteLock((void*)this);
96
1.74M
    }
AnnotatedMixin<std::recursive_mutex>::~AnnotatedMixin()
Line
Count
Source
94
321k
    ~AnnotatedMixin() {
95
321k
        DeleteLock((void*)this);
96
321k
    }
97
98
    void lock() EXCLUSIVE_LOCK_FUNCTION()
99
0
    {
100
0
        PARENT::lock();
101
0
    }
102
103
    void unlock() UNLOCK_FUNCTION()
104
0
    {
105
0
        PARENT::unlock();
106
0
    }
107
108
    bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)
109
    {
110
        return PARENT::try_lock();
111
    }
112
113
    using unique_lock = std::unique_lock<PARENT>;
114
#ifdef __clang__
115
    //! For negative capabilities in the Clang Thread Safety Analysis.
116
    //! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction
117
    //! with the ! operator, to indicate that a mutex should not be held.
118
    const AnnotatedMixin& operator!() const { return *this; }
119
#endif // __clang__
120
};
121
122
/**
123
 * Wrapped mutex: supports recursive locking, but no waiting
124
 * TODO: We should move away from using the recursive lock by default.
125
 */
126
using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
127
128
/** Wrapped mutex: supports waiting but not recursive locking */
129
using Mutex = AnnotatedMixin<std::mutex>;
130
131
/** Different type to mark Mutex at global scope
132
 *
133
 * Thread safety analysis can't handle negative assertions about mutexes
134
 * with global scope well, so mark them with a separate type, and
135
 * eventually move all the mutexes into classes so they are not globally
136
 * visible.
137
 *
138
 * See: https://github.com/bitcoin/bitcoin/pull/20272#issuecomment-720755781
139
 */
140
class GlobalMutex : public Mutex { };
141
142
402M
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
143
144
425M
inline void AssertLockNotHeldInline(const char* name, const char* file, int line, Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) { AssertLockNotHeldInternal(name, file, line, cs); }
145
15.9M
inline void AssertLockNotHeldInline(const char* name, const char* file, int line, RecursiveMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
146
0
inline void AssertLockNotHeldInline(const char* name, const char* file, int line, GlobalMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
147
441M
#define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
148
149
/** Wrapper around std::unique_lock style lock for MutexType. */
150
template <typename MutexType>
151
class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock
152
{
153
private:
154
    using Base = typename MutexType::unique_lock;
155
156
    void Enter(const char* pszName, const char* pszFile, int nLine)
157
2.30G
    {
158
2.30G
        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
2.30G
        Base::lock();
164
2.30G
    }
UniqueLock<AnnotatedMixin<std::recursive_mutex> >::Enter(char const*, char const*, int)
Line
Count
Source
157
1.13G
    {
158
1.13G
        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
1.13G
        Base::lock();
164
1.13G
    }
UniqueLock<AnnotatedMixin<std::mutex> >::Enter(char const*, char const*, int)
Line
Count
Source
157
1.15G
    {
158
1.15G
        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
1.15G
        Base::lock();
164
1.15G
    }
UniqueLock<GlobalMutex>::Enter(char const*, char const*, int)
Line
Count
Source
157
5.28M
    {
158
5.28M
        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
5.28M
        Base::lock();
164
5.28M
    }
165
166
    bool TryEnter(const char* pszName, const char* pszFile, int nLine)
167
11.0k
    {
168
11.0k
        EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);
169
11.0k
        if (Base::try_lock()) {
  Branch (169:13): [True: 0, False: 0]
  Branch (169:13): [True: 11.0k, False: 0]
  Branch (169:13): [True: 0, False: 0]
170
11.0k
            return true;
171
11.0k
        }
172
0
        LeaveCritical();
173
0
        return false;
174
11.0k
    }
Unexecuted instantiation: UniqueLock<AnnotatedMixin<std::recursive_mutex> >::TryEnter(char const*, char const*, int)
UniqueLock<AnnotatedMixin<std::mutex> >::TryEnter(char const*, char const*, int)
Line
Count
Source
167
11.0k
    {
168
11.0k
        EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);
169
11.0k
        if (Base::try_lock()) {
  Branch (169:13): [True: 11.0k, False: 0]
170
11.0k
            return true;
171
11.0k
        }
172
0
        LeaveCritical();
173
0
        return false;
174
11.0k
    }
Unexecuted instantiation: UniqueLock<GlobalMutex>::TryEnter(char const*, char const*, int)
175
176
public:
177
2.30G
    UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
178
2.30G
    {
179
2.30G
        if (fTry)
  Branch (179:13): [True: 0, False: 1.13G]
  Branch (179:13): [True: 11.0k, False: 1.15G]
  Branch (179:13): [True: 0, False: 5.28M]
180
11.0k
            TryEnter(pszName, pszFile, nLine);
181
2.30G
        else
182
2.30G
            Enter(pszName, pszFile, nLine);
183
2.30G
    }
UniqueLock<AnnotatedMixin<std::recursive_mutex> >::UniqueLock(AnnotatedMixin<std::recursive_mutex>&, char const*, char const*, int, bool)
Line
Count
Source
177
1.13G
    UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
178
1.13G
    {
179
1.13G
        if (fTry)
  Branch (179:13): [True: 0, False: 1.13G]
180
0
            TryEnter(pszName, pszFile, nLine);
181
1.13G
        else
182
1.13G
            Enter(pszName, pszFile, nLine);
183
1.13G
    }
UniqueLock<AnnotatedMixin<std::mutex> >::UniqueLock(AnnotatedMixin<std::mutex>&, char const*, char const*, int, bool)
Line
Count
Source
177
1.15G
    UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
178
1.15G
    {
179
1.15G
        if (fTry)
  Branch (179:13): [True: 11.0k, False: 1.15G]
180
11.0k
            TryEnter(pszName, pszFile, nLine);
181
1.15G
        else
182
1.15G
            Enter(pszName, pszFile, nLine);
183
1.15G
    }
UniqueLock<GlobalMutex>::UniqueLock(GlobalMutex&, char const*, char const*, int, bool)
Line
Count
Source
177
5.28M
    UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)
178
5.28M
    {
179
5.28M
        if (fTry)
  Branch (179:13): [True: 0, False: 5.28M]
180
0
            TryEnter(pszName, pszFile, nLine);
181
5.28M
        else
182
5.28M
            Enter(pszName, pszFile, nLine);
183
5.28M
    }
184
185
    UniqueLock(MutexType* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)
186
2.25M
    {
187
2.25M
        if (!pmutexIn) return;
  Branch (187:13): [True: 0, False: 2.25M]
188
189
2.25M
        *static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);
190
2.25M
        if (fTry)
  Branch (190:13): [True: 0, False: 2.25M]
191
0
            TryEnter(pszName, pszFile, nLine);
192
2.25M
        else
193
2.25M
            Enter(pszName, pszFile, nLine);
194
2.25M
    }
195
196
    ~UniqueLock() UNLOCK_FUNCTION()
197
2.36G
    {
198
2.36G
        if (Base::owns_lock())
  Branch (198:13): [True: 1.13G, False: 76.9k]
  Branch (198:13): [True: 1.15G, False: 60.9M]
  Branch (198:13): [True: 5.28M, False: 0]
199
2.30G
            LeaveCritical();
200
2.36G
    }
UniqueLock<AnnotatedMixin<std::recursive_mutex> >::~UniqueLock()
Line
Count
Source
197
1.13G
    {
198
1.13G
        if (Base::owns_lock())
  Branch (198:13): [True: 1.13G, False: 76.9k]
199
1.13G
            LeaveCritical();
200
1.13G
    }
UniqueLock<AnnotatedMixin<std::mutex> >::~UniqueLock()
Line
Count
Source
197
1.21G
    {
198
1.21G
        if (Base::owns_lock())
  Branch (198:13): [True: 1.15G, False: 60.9M]
199
1.15G
            LeaveCritical();
200
1.21G
    }
UniqueLock<GlobalMutex>::~UniqueLock()
Line
Count
Source
197
5.28M
    {
198
5.28M
        if (Base::owns_lock())
  Branch (198:13): [True: 5.28M, False: 0]
199
5.28M
            LeaveCritical();
200
5.28M
    }
201
202
    operator bool()
203
11.0k
    {
204
11.0k
        return Base::owns_lock();
205
11.0k
    }
UniqueLock<AnnotatedMixin<std::mutex> >::operator bool()
Line
Count
Source
203
11.0k
    {
204
11.0k
        return Base::owns_lock();
205
11.0k
    }
Unexecuted instantiation: UniqueLock<AnnotatedMixin<std::recursive_mutex> >::operator bool()
206
207
protected:
208
    // needed for reverse_lock
209
61.1M
    UniqueLock() = default;
Unexecuted instantiation: UniqueLock<AnnotatedMixin<std::recursive_mutex> >::UniqueLock()
UniqueLock<AnnotatedMixin<std::mutex> >::UniqueLock()
Line
Count
Source
209
61.1M
    UniqueLock() = default;
210
211
public:
212
    /**
213
     * An RAII-style reverse lock. Unlocks on construction and locks on destruction.
214
     */
215
    class reverse_lock {
216
    public:
217
61.1M
        explicit reverse_lock(UniqueLock& _lock, const char* _guardname, const char* _file, int _line) : lock(_lock), file(_file), line(_line) {
218
61.1M
            CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);
219
61.1M
            lock.unlock();
220
61.1M
            LeaveCritical();
221
61.1M
            lock.swap(templock);
222
61.1M
        }
Unexecuted instantiation: UniqueLock<AnnotatedMixin<std::recursive_mutex> >::reverse_lock::reverse_lock(UniqueLock<AnnotatedMixin<std::recursive_mutex> >&, char const*, char const*, int)
UniqueLock<AnnotatedMixin<std::mutex> >::reverse_lock::reverse_lock(UniqueLock<AnnotatedMixin<std::mutex> >&, char const*, char const*, int)
Line
Count
Source
217
61.1M
        explicit reverse_lock(UniqueLock& _lock, const char* _guardname, const char* _file, int _line) : lock(_lock), file(_file), line(_line) {
218
61.1M
            CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);
219
61.1M
            lock.unlock();
220
61.1M
            LeaveCritical();
221
61.1M
            lock.swap(templock);
222
61.1M
        }
223
224
61.1M
        ~reverse_lock() {
225
61.1M
            templock.swap(lock);
226
61.1M
            EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());
227
61.1M
            lock.lock();
228
61.1M
        }
Unexecuted instantiation: UniqueLock<AnnotatedMixin<std::recursive_mutex> >::reverse_lock::~reverse_lock()
UniqueLock<AnnotatedMixin<std::mutex> >::reverse_lock::~reverse_lock()
Line
Count
Source
224
61.1M
        ~reverse_lock() {
225
61.1M
            templock.swap(lock);
226
61.1M
            EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());
227
61.1M
            lock.lock();
228
61.1M
        }
229
230
     private:
231
        reverse_lock(reverse_lock const&);
232
        reverse_lock& operator=(reverse_lock const&);
233
234
        UniqueLock& lock;
235
        UniqueLock templock;
236
        std::string lockname;
237
        const std::string file;
238
        const int line;
239
     };
240
     friend class reverse_lock;
241
};
242
243
61.1M
#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
247
1.21G
inline Mutex& MaybeCheckNotHeld(Mutex& cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
248
0
inline Mutex* MaybeCheckNotHeld(Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) LOCK_RETURNED(cs) { return cs; }
249
250
// When locking a GlobalMutex or RecursiveMutex, just check it is not
251
// locked in the surrounding scope.
252
template <typename MutexType>
253
1.16G
inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
AnnotatedMixin<std::recursive_mutex>& MaybeCheckNotHeld<AnnotatedMixin<std::recursive_mutex> >(AnnotatedMixin<std::recursive_mutex>&)
Line
Count
Source
253
1.15G
inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
GlobalMutex& MaybeCheckNotHeld<GlobalMutex>(GlobalMutex&)
Line
Count
Source
253
5.29M
inline MutexType& MaybeCheckNotHeld(MutexType& m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
254
template <typename MutexType>
255
2.25M
inline MutexType* MaybeCheckNotHeld(MutexType* m) LOCKS_EXCLUDED(m) LOCK_RETURNED(m) { return m; }
256
257
2.18G
#define LOCK(cs) UniqueLock UNIQUE_NAME(criticalblock)(MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__)
258
#define LOCK2(cs1, cs2)                                               \
259
43.3M
    UniqueLock criticalblock1(MaybeCheckNotHeld(cs1), #cs1, __FILE__, __LINE__); \
260
43.3M
    UniqueLock criticalblock2(MaybeCheckNotHeld(cs2), #cs2, __FILE__, __LINE__)
261
26.0M
#define LOCK_ARGS(cs) MaybeCheckNotHeld(cs), #cs, __FILE__, __LINE__
262
11.0k
#define TRY_LOCK(cs, name) UniqueLock name(LOCK_ARGS(cs), true)
263
23.7M
#define WAIT_LOCK(cs, name) UniqueLock name(LOCK_ARGS(cs))
264
265
#define ENTER_CRITICAL_SECTION(cs)                            \
266
0
    {                                                         \
267
0
        EnterCritical(#cs, __FILE__, __LINE__, &cs); \
268
0
        (cs).lock();                                          \
269
0
    }
270
271
#define LEAVE_CRITICAL_SECTION(cs)                                          \
272
0
    {                                                                       \
273
0
        std::string lockname;                                               \
274
0
        CheckLastCritical((void*)(&cs), lockname, #cs, __FILE__, __LINE__); \
275
0
        (cs).unlock();                                                      \
276
0
        LeaveCritical();                                                    \
277
0
    }
278
279
//! Run code while locking a mutex.
280
//!
281
//! Examples:
282
//!
283
//!   WITH_LOCK(cs, shared_val = shared_val + 1);
284
//!
285
//!   int val = WITH_LOCK(cs, return shared_val);
286
//!
287
//! Note:
288
//!
289
//! Since the return type deduction follows that of decltype(auto), while the
290
//! deduced type of:
291
//!
292
//!   WITH_LOCK(cs, return {int i = 1; return i;});
293
//!
294
//! is int, the deduced type of:
295
//!
296
//!   WITH_LOCK(cs, return {int j = 1; return (j);});
297
//!
298
//! is &int, a reference to a local variable
299
//!
300
//! The above is detectable at compile-time with the -Wreturn-local-addr flag in
301
//! gcc and the -Wreturn-stack-address flag in clang, both enabled by default.
302
75.3M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
CScheduler::stop()::{lambda()#1}::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
init.cpp:AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_7::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
init.cpp:AppInitMain(node::NodeContext&, interfaces::BlockAndHeaderTipInfo*)::$_8::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
init.cpp:StartIndexBackgroundSync(node::NodeContext&)::$_0::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
init.cpp:InitContext(node::NodeContext&)::$_0::operator()() const::{lambda()#1}::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
V1Transport::ReceivedMessageComplete() const::{lambda()#1}::operator()() const
Line
Count
Source
302
10.9M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
net.cpp:CConnman::AddConnection(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, ConnectionType, bool)::$_0::operator()() const
Line
Count
Source
302
44.3k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: net.cpp:CConnman::SocketHandlerConnected(std::vector<CNode*, std::allocator<CNode*> > const&, std::unordered_map<std::shared_ptr<Sock const>, Sock::Events, Sock::HashSharedPtrSock, Sock::EqualSharedPtrSock, std::allocator<std::pair<std::shared_ptr<Sock const> const, Sock::Events> > > const&)::$_0::operator()() const
net.cpp:CConnman::StopNodes()::$_0::operator()() const
Line
Count
Source
302
22.1k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
net_processing.cpp:(anonymous namespace)::Peer::GetTxRelay()::{lambda()#1}::operator()() const
Line
Count
Source
302
43.5M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: net_processing.cpp:(anonymous namespace)::PeerManagerImpl::GetNodeStateStats(long, CNodeStateStats&) const::$_0::operator()() const
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&)::$_0::operator()() const
Line
Count
Source
302
88.7k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&)::$_2::operator()() const
Unexecuted instantiation: net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessGetBlockData(CNode&, (anonymous namespace)::Peer&, CInv const&)::$_0::operator()() const
Unexecuted instantiation: net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessGetBlockData(CNode&, (anonymous namespace)::Peer&, CInv const&)::$_1::operator()() const
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&)::$_3::operator()() const
Line
Count
Source
302
9.80k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&)::$_4::operator()() const
Unexecuted instantiation: net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&)::$_5::operator()() const
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessHeadersMessage(CNode&, (anonymous namespace)::Peer&, std::vector<CBlockHeader, std::allocator<CBlockHeader> >&&, bool)::$_0::operator()() const
Line
Count
Source
302
21.4k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::HandleUnconnectingHeaders(CNode&, (anonymous namespace)::Peer&, std::vector<CBlockHeader, std::allocator<CBlockHeader> > const&)::$_0::operator()() const
Line
Count
Source
302
707
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::HandleUnconnectingHeaders(CNode&, (anonymous namespace)::Peer&, std::vector<CBlockHeader, std::allocator<CBlockHeader> > const&)::$_1::operator()() const
Line
Count
Source
302
707
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&)::$_6::operator()() const
Line
Count
Source
302
2.24M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::ProcessMessage(CNode&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, DataStream&, std::chrono::duration<long, std::ratio<1l, 1000000l> >, std::atomic<bool> const&)::$_7::operator()() const
Line
Count
Source
302
158
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::InitializeNode(CNode const&, ServiceFlags)::$_0::operator()() const
Line
Count
Source
302
88.7k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
net_processing.cpp:(anonymous namespace)::PeerManagerImpl::FinalizeNode(CNode const&)::$_0::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
blockstorage.cpp:node::BlockManager::WriteBlockIndexDB()::$_0::operator()() const
Line
Count
Source
302
29.2k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
blockstorage.cpp:node::BlockManager::ScanAndUnlinkAlreadyPrunedFiles()::$_0::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
blockstorage.cpp:node::BlockManager::ReadBlockUndo(CBlockUndo&, CBlockIndex const&) const::$_0::operator()() const
Line
Count
Source
302
2.22M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
blockstorage.cpp:node::BlockManager::ReadBlock(CBlock&, CBlockIndex const&) const::$_0::operator()() const
Line
Count
Source
302
21.5k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: blockstorage.cpp:node::ImportBlocks(ChainstateManager&, std::span<fs::path const, 18446744073709551615ul>)::$_0::operator()() const
blockstorage.cpp:node::ImportBlocks(ChainstateManager&, std::span<fs::path const, 18446744073709551615ul>)::$_1::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: interfaces.cpp:node::(anonymous namespace)::NodeImpl::getBestBlockHash()::{lambda()#1}::operator()() const
Unexecuted instantiation: interfaces.cpp:node::(anonymous namespace)::NodeImpl::getVerificationProgress()::{lambda()#1}::operator()() const
interfaces.cpp:node::(anonymous namespace)::ChainImpl::getHeight()::{lambda()#1}::operator()() const
Line
Count
Source
302
33.2k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: interfaces.cpp:node::(anonymous namespace)::ChainImpl::blockFilterMatchesAny(BlockFilterType, uint256 const&, std::unordered_set<std::vector<unsigned char, std::allocator<unsigned char> >, ByteVectorHash, std::equal_to<std::vector<unsigned char, std::allocator<unsigned char> > >, std::allocator<std::vector<unsigned char, std::allocator<unsigned char> > > > const&)::{lambda()#1}::operator()() const
Unexecuted instantiation: interfaces.cpp:node::(anonymous namespace)::ChainImpl::waitForNotificationsIfTipChanged(uint256 const&)::{lambda()#1}::operator()() const
Unexecuted instantiation: miner.cpp:node::RegenerateCommitments(CBlock&, ChainstateManager&)::$_0::operator()() const
warnings.cpp:node::Warnings::Set(std::variant<kernel::Warning, node::Warning>, bilingual_str)::$_0::operator()() const
Line
Count
Source
302
39
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
warnings.cpp:node::Warnings::Unset(std::variant<kernel::Warning, node::Warning>)::$_0::operator()() const
Line
Count
Source
302
2.27M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: fees.cpp:FeeFilterRounder::round(long)::$_0::operator()() const
Unexecuted instantiation: rest.cpp:rest_deploymentinfo(std::any const&, HTTPRequest*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)::$_0::operator()() const
Unexecuted instantiation: blockchain.cpp:blockToJSON(node::BlockManager&, CBlock const&, CBlockIndex const&, CBlockIndex const&, TxVerbosity, uint256)::$_0::operator()() const
Unexecuted instantiation: blockchain.cpp:blockToJSON(node::BlockManager&, CBlock const&, CBlockIndex const&, CBlockIndex const&, TxVerbosity, uint256)::$_1::operator()() const
Unexecuted instantiation: blockchain.cpp:CreateUTXOSnapshot(node::NodeContext&, Chainstate&, AutoFile&, fs::path const&, fs::path const&)::$_0::operator()() const
Unexecuted instantiation: blockchain.cpp:getblockfrompeer()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#1}::operator()() const
Unexecuted instantiation: blockchain.cpp:getblockfrompeer()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#2}::operator()() const
Unexecuted instantiation: blockchain.cpp:getblockfrompeer()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#3}::operator()() const
Unexecuted instantiation: blockchain.cpp:scanblocks()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#1}::operator()() const
Unexecuted instantiation: blockchain.cpp:dumptxoutset()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#1}::operator()() const
Unexecuted instantiation: blockchain.cpp:dumptxoutset()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#2}::operator()() const
Unexecuted instantiation: mempool.cpp:submitpackage()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#1}::operator()() const
Unexecuted instantiation: rawtransaction.cpp:getrawtransaction()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#1}::operator()() const
Unexecuted instantiation: rawtransaction.cpp:getrawtransaction()::$_0::operator()(RPCHelpMan const&, JSONRPCRequest const&) const::{lambda()#2}::operator()() const
server.cpp:StopRPC()::$_0::operator()() const::{lambda()#1}::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
validation.cpp:Chainstate::ActivateBestChain(BlockValidationState&, std::shared_ptr<CBlock const>)::$_0::operator()() const
Line
Count
Source
302
2.25M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
validation.cpp:Chainstate::ActivateBestChain(BlockValidationState&, std::shared_ptr<CBlock const>)::$_1::operator()() const
Line
Count
Source
302
2.23M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
validation.cpp:ChainstateManager::ProcessNewBlock(std::shared_ptr<CBlock const> const&, bool, bool, bool*)::$_0::operator()() const
Line
Count
Source
302
4.48M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
  Branch (302:89): [True: 0, False: 2.24M]
Unexecuted instantiation: validation.cpp:ChainstateManager::LoadExternalBlockFile(AutoFile&, FlatFilePos*, std::multimap<uint256, FlatFilePos, std::less<uint256>, std::allocator<std::pair<uint256 const, FlatFilePos> > >*)::$_0::operator()() const
Unexecuted instantiation: validation.cpp:ChainstateManager::ActivateSnapshot(AutoFile&, node::SnapshotMetadata const&, bool)::$_1::operator()() const
Unexecuted instantiation: validation.cpp:ChainstateManager::PopulateAndValidateSnapshot(Chainstate&, AutoFile&, node::SnapshotMetadata const&)::$_1::operator()() const
Unexecuted instantiation: validation.cpp:ChainstateManager::PopulateAndValidateSnapshot(Chainstate&, AutoFile&, node::SnapshotMetadata const&)::$_2::operator()() const
Unexecuted instantiation: validation.cpp:ChainstateManager::PopulateAndValidateSnapshot(Chainstate&, AutoFile&, node::SnapshotMetadata const&)::$_3::operator()() const
Unexecuted instantiation: validation.cpp:ChainstateManager::PopulateAndValidateSnapshot(Chainstate&, AutoFile&, node::SnapshotMetadata const&)::$_4::operator()() const
Unexecuted instantiation: validation.cpp:ChainstateManager::PopulateAndValidateSnapshot(Chainstate&, AutoFile&, node::SnapshotMetadata const&)::$_5::operator()() const
CCheckQueue<CScriptCheck, std::pair<ScriptError_t, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >::~CCheckQueue()::{lambda()#1}::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
HTTPRequestTracker::AddRequest(evhttp_request*)::{lambda()#1}::operator()() const
Line
Count
Source
302
2.35M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
HTTPRequestTracker::CountActiveConnections() const::{lambda()#1}::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
base.cpp:BaseIndex::Init()::$_0::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: base.cpp:BaseIndex::Sync()::$_0::operator()() const
base.cpp:BaseIndex::SetBestBlockIndex(CBlockIndex const*)::$_0::operator()() const
Line
Count
Source
302
2.23M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
blockfilterindex.cpp:BlockFilterIndex::CustomAppend(interfaces::BlockInfo const&)::$_0::operator()() const
Line
Count
Source
302
2.22M
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: coinstatsindex.cpp:CoinStatsIndex::CustomAppend(interfaces::BlockInfo const&)::$_0::operator()() const
Unexecuted instantiation: coinstats.cpp:kernel::ComputeUTXOStats(kernel::CoinStatsHashType, CCoinsView*, node::BlockManager&, std::function<void ()> const&)::$_0::operator()() const
Unexecuted instantiation: scriptpubkeyman.cpp:wallet::LegacyDataSPKM::MigrateToDescriptor()::$_0::operator()() const
Unexecuted instantiation: scriptpubkeyman.cpp:wallet::LegacyDataSPKM::MigrateToDescriptor()::$_1::operator()() const
Unexecuted instantiation: scriptpubkeyman.cpp:wallet::LegacyDataSPKM::MigrateToDescriptor()::$_2::operator()() const
wallet.cpp:wallet::RemoveWallet(wallet::WalletContext&, std::shared_ptr<wallet::CWallet> const&, std::optional<bool>, std::vector<bilingual_str, std::allocator<bilingual_str> >&)::$_0::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: wallet.cpp:wallet::LoadWallet(wallet::WalletContext&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::optional<bool>, wallet::DatabaseOptions const&, wallet::DatabaseStatus&, bilingual_str&, std::vector<bilingual_str, std::allocator<bilingual_str> >&)::$_0::operator()[abi:cxx11]() const
Unexecuted instantiation: wallet.cpp:wallet::LoadWallet(wallet::WalletContext&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::optional<bool>, wallet::DatabaseOptions const&, wallet::DatabaseStatus&, bilingual_str&, std::vector<bilingual_str, std::allocator<bilingual_str> >&)::$_1::operator()() const
Unexecuted instantiation: wallet.cpp:wallet::CWallet::BlockUntilSyncedToCurrentChain() const::$_0::operator()() const
Unexecuted instantiation: wallet.cpp:wallet::CWallet::RescanFromTime(long, wallet::WalletRescanReserver const&, bool)::$_0::operator()() const
Unexecuted instantiation: wallet.cpp:wallet::CWallet::ScanForWalletTransactions(uint256 const&, int, std::optional<int>, wallet::WalletRescanReserver const&, bool, bool)::$_0::operator()() const
Unexecuted instantiation: wallet.cpp:wallet::CWallet::ScanForWalletTransactions(uint256 const&, int, std::optional<int>, wallet::WalletRescanReserver const&, bool, bool)::$_1::operator()() const
Unexecuted instantiation: wallet.cpp:wallet::CWallet::ScanForWalletTransactions(uint256 const&, int, std::optional<int>, wallet::WalletRescanReserver const&, bool, bool)::$_2::operator()() const
Unexecuted instantiation: wallet.cpp:wallet::CWallet::ScanForWalletTransactions(uint256 const&, int, std::optional<int>, wallet::WalletRescanReserver const&, bool, bool)::$_3::operator()() const
wallet.cpp:wallet::CWallet::postInitProcess()::$_0::operator()() const
Line
Count
Source
302
11.0k
#define WITH_LOCK(cs, code) (MaybeCheckNotHeld(cs), [&]() -> decltype(auto) { LOCK(cs); code; }())
Unexecuted instantiation: wallet.cpp:wallet::CWallet::BackupWallet(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) const::$_0::operator()() const
  Branch (302:89): [True: 0, False: 2.24M]
303
304
#endif // BITCOIN_SYNC_H