Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2009-2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#ifndef BITCOIN_SYNC_H7#define BITCOIN_SYNC_H9// This header declares threading primitives compatible with Clang10// Thread Safety Analysis and provides appropriate annotation macros.11#include <threadsafety.h> // IWYU pragma: export12#include <util/macros.h>14#include <cassert>15#include <condition_variable>16#include <mutex>17#include <string>18#include <thread>20////////////////////////////////////////////////21// //22// THE SIMPLE DEFINITION, EXCLUDING DEBUG CODE //23// //24////////////////////////////////////////////////26/*27RecursiveMutex mutex;28std::recursive_mutex mutex;30LOCK(mutex);31std::unique_lock<std::recursive_mutex> criticalblock(mutex);33LOCK2(mutex1, mutex2);34std::unique_lock<std::recursive_mutex> criticalblock1(mutex1);35std::unique_lock<std::recursive_mutex> criticalblock2(mutex2);37TRY_LOCK(mutex, name);38std::unique_lock<std::recursive_mutex> name(mutex, std::try_to_lock_t);39*/41///////////////////////////////42// //43// THE ACTUAL IMPLEMENTATION //44// //45///////////////////////////////47#ifdef DEBUG_LOCKORDER48template <typename MutexType>49void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false);50void LeaveCritical();51void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);52template <typename MutexType>53void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs);54template <typename MutexType>55void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs);56void DeleteLock(void* cs);57bool LockStackEmpty();59/**60* Call abort() if a potential lock order deadlock bug is detected, instead of61* just logging information and throwing a logic_error. Defaults to true, and62* set to false in DEBUG_LOCKORDER unit tests.63*/64extern bool g_debug_lockorder_abort;65#else66template <typename MutexType>67inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, MutexType* cs, bool fTry = false) {}68inline void LeaveCritical() {}69inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}70template <typename MutexType>71inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}72template <typename MutexType>73void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) LOCKS_EXCLUDED(cs) {}74inline void DeleteLock(void* cs) {}75inline bool LockStackEmpty() { return true; }76#endif78/*79* Called when a mutex fails to lock immediately because it is held by another80* thread, or spuriously. Responsible for locking the lock before returning.81*/82#ifdef DEBUG_LOCKCONTENTION84template <typename LockType>85void ContendedLock(std::string_view name, std::string_view file, int nLine, LockType& lock);86#endif88/**89* Template mixin that adds -Wthread-safety locking annotations and lock order90* checking to a subset of the mutex API.91*/92template <typename PARENT>93class LOCKABLE AnnotatedMixin : public PARENT94{95public:96~AnnotatedMixin() {97DeleteLock((void*)this);98}100void lock() EXCLUSIVE_LOCK_FUNCTION()101{102PARENT::lock();103}105void unlock() UNLOCK_FUNCTION()106{107PARENT::unlock();108}110bool try_lock() EXCLUSIVE_TRYLOCK_FUNCTION(true)111{112return PARENT::try_lock();113}115using unique_lock = std::unique_lock<PARENT>;116#ifdef __clang__117//! For negative capabilities in the Clang Thread Safety Analysis.118//! A negative requirement uses the EXCLUSIVE_LOCKS_REQUIRED attribute, in conjunction119//! with the ! operator, to indicate that a mutex should not be held.120const AnnotatedMixin& operator!() const { return *this; }121#endif // __clang__122};124/**125* Wrapped mutex: supports recursive locking, but no waiting126* TODO: We should move away from using the recursive lock by default.127*/128using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;130/** Wrapped mutex: supports waiting but not recursive locking */131using Mutex = AnnotatedMixin<std::mutex>;133/** Different type to mark Mutex at global scope134*135* Thread safety analysis can't handle negative assertions about mutexes136* with global scope well, so mark them with a separate type, and137* eventually move all the mutexes into classes so they are not globally138* visible.139*140* See: https://github.com/bitcoin/bitcoin/pull/20272#issuecomment-720755781141*/142class GlobalMutex : public Mutex { };144#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)146inline void AssertLockNotHeldInline(const char* name, const char* file, int line, Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) { AssertLockNotHeldInternal(name, file, line, cs); }147inline void AssertLockNotHeldInline(const char* name, const char* file, int line, RecursiveMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }148inline void AssertLockNotHeldInline(const char* name, const char* file, int line, GlobalMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }149#define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)151/** Wrapper around std::unique_lock style lock for MutexType. */152template <typename MutexType>153class SCOPED_LOCKABLE UniqueLock : public MutexType::unique_lock154{155private:156using Base = typename MutexType::unique_lock;158void Enter(const char* pszName, const char* pszFile, int nLine)159{160EnterCritical(pszName, pszFile, nLine, Base::mutex());161#ifdef DEBUG_LOCKCONTENTION162if (!Base::try_lock()) {163ContendedLock(pszName, pszFile, nLine, static_cast<Base&>(*this));164}165#else166Base::lock();167#endif168}170bool TryEnter(const char* pszName, const char* pszFile, int nLine)171{172EnterCritical(pszName, pszFile, nLine, Base::mutex(), true);173if (Base::try_lock()) {174return true;175}176LeaveCritical();177return false;178}180public:181UniqueLock(MutexType& mutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(mutexIn) : Base(mutexIn, std::defer_lock)182{183if (fTry)184TryEnter(pszName, pszFile, nLine);185else186Enter(pszName, pszFile, nLine);187}189UniqueLock(MutexType* pmutexIn, const char* pszName, const char* pszFile, int nLine, bool fTry = false) EXCLUSIVE_LOCK_FUNCTION(pmutexIn)190{191if (!pmutexIn) return;193*static_cast<Base*>(this) = Base(*pmutexIn, std::defer_lock);194if (fTry)195TryEnter(pszName, pszFile, nLine);196else197Enter(pszName, pszFile, nLine);198}200~UniqueLock() UNLOCK_FUNCTION()201{202if (Base::owns_lock())203LeaveCritical();204}206operator bool()207{208return Base::owns_lock();209}211protected:212// needed for reverse_lock213UniqueLock() = default;215public:216/**217* An RAII-style reverse lock. Unlocks on construction and locks on destruction.218*/219class SCOPED_LOCKABLE reverse_lock {220public:221explicit reverse_lock(UniqueLock& _lock, const MutexType& mutex, const char* _guardname, const char* _file, int _line) UNLOCK_FUNCTION(mutex) : lock(_lock), file(_file), line(_line) {222// Ensure that mutex passed back for thread-safety analysis is indeed the original223assert(std::addressof(mutex) == lock.mutex());225CheckLastCritical((void*)lock.mutex(), lockname, _guardname, _file, _line);226lock.unlock();227LeaveCritical();228lock.swap(templock);229}231~reverse_lock() UNLOCK_FUNCTION() {232templock.swap(lock);233EnterCritical(lockname.c_str(), file.c_str(), line, lock.mutex());234lock.lock();235}237private:238reverse_lock(reverse_lock const&);239reverse_lock& operator=(reverse_lock const&);241UniqueLock& lock;242UniqueLock templock;243std::string lockname;244const std::string file;245const int line;246};247friend class reverse_lock;248};250// clang's thread-safety analyzer is unable to deal with aliases of mutexes, so
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.