0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-03 09:56:38 -05:00

Merge bitcoin/bitcoin#25109: Strengthen AssertLockNotHeld assertions

436ce0233c sync.h: strengthen AssertLockNotHeld assertion (Anthony Towns)
7d73f58e9c Increase threadsafety annotation coverage (Anthony Towns)

Pull request description:

  This changes `AssertLockNotHeld` so that it is annotated with the negative capability for the mutex it refers to. clang applies negative capabilities recursively, so this helps avoid forgetting to annotate functions.

  Note that this can't reasonably be used for globals, because clang would require every function to be annotated with `EXCLUSIVE_LOCKS_REQUIRED(!g_mutex)` for each global mutex. At present, the only global mutexes that use `AssertLockNotHeld` are `RecursiveMutex` so we treat that as an exception in order to avoid having to add an excessive number of negative annotations.

ACKs for top commit:
  vasild:
    ACK 436ce0233c
  MarcoFalke:
    review ACK 436ce0233c 🌺

Tree-SHA512: 5f16d098790a36b5277324d5ee89cdc87033c19b11c7943c2f630a41c2e3998eb39d356a763e857f4d8fefb6c0c02291f720bb6769bcbdf5e2cd765bf266ab8c
This commit is contained in:
MacroFake 2022-05-16 14:17:57 +02:00
commit aa3200d896
No known key found for this signature in database
GPG key ID: CE2B75697E69A548
13 changed files with 108 additions and 89 deletions

View file

@ -66,7 +66,7 @@ private:
bool m_request_stop GUARDED_BY(m_mutex){false}; bool m_request_stop GUARDED_BY(m_mutex){false};
/** Internal function that does bulk of the verification work. */ /** Internal function that does bulk of the verification work. */
bool Loop(bool fMaster) bool Loop(bool fMaster) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
std::condition_variable& cond = fMaster ? m_master_cv : m_worker_cv; std::condition_variable& cond = fMaster ? m_master_cv : m_worker_cv;
std::vector<T> vChecks; std::vector<T> vChecks;
@ -140,7 +140,7 @@ public:
} }
//! Create a pool of new worker threads. //! Create a pool of new worker threads.
void StartWorkerThreads(const int threads_num) void StartWorkerThreads(const int threads_num) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
{ {
LOCK(m_mutex); LOCK(m_mutex);
@ -159,13 +159,13 @@ public:
} }
//! Wait until execution finishes, and return whether all evaluations were successful. //! Wait until execution finishes, and return whether all evaluations were successful.
bool Wait() bool Wait() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
return Loop(true /* master thread */); return Loop(true /* master thread */);
} }
//! Add a batch of checks to the queue //! Add a batch of checks to the queue
void Add(std::vector<T>& vChecks) void Add(std::vector<T>& vChecks) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
if (vChecks.empty()) { if (vChecks.empty()) {
return; return;
@ -188,7 +188,7 @@ public:
} }
//! Stop all of the worker threads. //! Stop all of the worker threads.
void StopWorkerThreads() void StopWorkerThreads() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
WITH_LOCK(m_mutex, m_request_stop = true); WITH_LOCK(m_mutex, m_request_stop = true);
m_worker_cv.notify_all(); m_worker_cv.notify_all();

View file

@ -87,7 +87,7 @@ public:
{ {
} }
/** Enqueue a work item */ /** Enqueue a work item */
bool Enqueue(WorkItem* item) bool Enqueue(WorkItem* item) EXCLUSIVE_LOCKS_REQUIRED(!cs)
{ {
LOCK(cs); LOCK(cs);
if (!running || queue.size() >= maxDepth) { if (!running || queue.size() >= maxDepth) {
@ -98,7 +98,7 @@ public:
return true; return true;
} }
/** Thread function */ /** Thread function */
void Run() void Run() EXCLUSIVE_LOCKS_REQUIRED(!cs)
{ {
while (true) { while (true) {
std::unique_ptr<WorkItem> i; std::unique_ptr<WorkItem> i;
@ -115,7 +115,7 @@ public:
} }
} }
/** Interrupt and exit loops */ /** Interrupt and exit loops */
void Interrupt() void Interrupt() EXCLUSIVE_LOCKS_REQUIRED(!cs)
{ {
LOCK(cs); LOCK(cs);
running = false; running = false;

View file

@ -84,7 +84,7 @@ public:
* to the listening socket and address. * to the listening socket and address.
* @return true on success * @return true on success
*/ */
bool Listen(Connection& conn); bool Listen(Connection& conn) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
/** /**
* Wait for and accept a new incoming connection. * Wait for and accept a new incoming connection.
@ -103,7 +103,7 @@ public:
* it is set to `false`. Only set if `false` is returned. * it is set to `false`. Only set if `false` is returned.
* @return true on success * @return true on success
*/ */
bool Connect(const CService& to, Connection& conn, bool& proxy_error); bool Connect(const CService& to, Connection& conn, bool& proxy_error) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
private: private:
/** /**
@ -172,7 +172,7 @@ private:
/** /**
* Check the control socket for errors and possibly disconnect. * Check the control socket for errors and possibly disconnect.
*/ */
void CheckControlSock(); void CheckControlSock() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
/** /**
* Generate a new destination with the SAM proxy and set `m_private_key` to it. * Generate a new destination with the SAM proxy and set `m_private_key` to it.

View file

@ -64,7 +64,7 @@ public:
bool LookupFilter(const CBlockIndex* block_index, BlockFilter& filter_out) const; bool LookupFilter(const CBlockIndex* block_index, BlockFilter& filter_out) const;
/** Get a single filter header by block. */ /** Get a single filter header by block. */
bool LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out); bool LookupFilterHeader(const CBlockIndex* block_index, uint256& header_out) EXCLUSIVE_LOCKS_REQUIRED(!m_cs_headers_cache);
/** Get a range of filters between two heights on a chain. */ /** Get a range of filters between two heights on a chain. */
bool LookupFilterRange(int start_height, const CBlockIndex* stop_index, bool LookupFilterRange(int start_height, const CBlockIndex* stop_index,

View file

@ -612,7 +612,7 @@ public:
* @return True if the peer should stay connected, * @return True if the peer should stay connected,
* False if the peer should be disconnected from. * False if the peer should be disconnected from.
*/ */
bool ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete); bool ReceiveMsgBytes(Span<const uint8_t> msg_bytes, bool& complete) EXCLUSIVE_LOCKS_REQUIRED(!cs_vRecv);
void SetCommonVersion(int greatest_common_version) void SetCommonVersion(int greatest_common_version)
{ {
@ -624,9 +624,9 @@ public:
return m_greatest_common_version; return m_greatest_common_version;
} }
CService GetAddrLocal() const LOCKS_EXCLUDED(m_addr_local_mutex); CService GetAddrLocal() const EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex);
//! May not be called more than once //! May not be called more than once
void SetAddrLocal(const CService& addrLocalIn) LOCKS_EXCLUDED(m_addr_local_mutex); void SetAddrLocal(const CService& addrLocalIn) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_local_mutex);
CNode* AddRef() CNode* AddRef()
{ {
@ -639,9 +639,9 @@ public:
nRefCount--; nRefCount--;
} }
void CloseSocketDisconnect(); void CloseSocketDisconnect() EXCLUSIVE_LOCKS_REQUIRED(!m_sock_mutex);
void CopyStats(CNodeStats& stats); void CopyStats(CNodeStats& stats) EXCLUSIVE_LOCKS_REQUIRED(!m_subver_mutex, !m_addr_local_mutex, !cs_vSend, !cs_vRecv);
ServiceFlags GetLocalServices() const ServiceFlags GetLocalServices() const
{ {
@ -760,7 +760,7 @@ public:
bool m_i2p_accept_incoming; bool m_i2p_accept_incoming;
}; };
void Init(const Options& connOptions) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex) void Init(const Options& connOptions) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_total_bytes_sent_mutex)
{ {
AssertLockNotHeld(m_total_bytes_sent_mutex); AssertLockNotHeld(m_total_bytes_sent_mutex);
@ -794,7 +794,8 @@ public:
bool network_active = true); bool network_active = true);
~CConnman(); ~CConnman();
bool Start(CScheduler& scheduler, const Options& options) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex);
bool Start(CScheduler& scheduler, const Options& options) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !m_added_nodes_mutex, !m_addr_fetches_mutex, !mutexMsgProc);
void StopThreads(); void StopThreads();
void StopNodes(); void StopNodes();
@ -804,7 +805,7 @@ public:
StopNodes(); StopNodes();
}; };
void Interrupt(); void Interrupt() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
bool GetNetworkActive() const { return fNetworkActive; }; bool GetNetworkActive() const { return fNetworkActive; };
bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; }; bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };
void SetNetworkActive(bool active); void SetNetworkActive(bool active);
@ -868,9 +869,9 @@ public:
// Count the number of block-relay-only peers we have over our limit. // Count the number of block-relay-only peers we have over our limit.
int GetExtraBlockRelayCount() const; int GetExtraBlockRelayCount() const;
bool AddNode(const std::string& node); bool AddNode(const std::string& node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
bool RemoveAddedNode(const std::string& node); bool RemoveAddedNode(const std::string& node) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
std::vector<AddedNodeInfo> GetAddedNodeInfo() const; std::vector<AddedNodeInfo> GetAddedNodeInfo() const EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
/** /**
* Attempts to open a connection. Currently only used from tests. * Attempts to open a connection. Currently only used from tests.
@ -923,7 +924,7 @@ public:
unsigned int GetReceiveFloodSize() const; unsigned int GetReceiveFloodSize() const;
void WakeMessageHandler(); void WakeMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
/** Return true if we should disconnect the peer for failing an inactivity check. */ /** Return true if we should disconnect the peer for failing an inactivity check. */
bool ShouldRunInactivityChecks(const CNode& node, std::chrono::seconds now) const; bool ShouldRunInactivityChecks(const CNode& node, std::chrono::seconds now) const;
@ -950,11 +951,11 @@ private:
bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions); bool Bind(const CService& addr, unsigned int flags, NetPermissionFlags permissions);
bool InitBinds(const Options& options); bool InitBinds(const Options& options);
void ThreadOpenAddedConnections(); void ThreadOpenAddedConnections() EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex);
void AddAddrFetch(const std::string& strDest); void AddAddrFetch(const std::string& strDest) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex);
void ProcessAddrFetch(); void ProcessAddrFetch() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex);
void ThreadOpenConnections(std::vector<std::string> connect); void ThreadOpenConnections(std::vector<std::string> connect) EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_added_nodes_mutex, !m_nodes_mutex);
void ThreadMessageHandler(); void ThreadMessageHandler() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);
void ThreadI2PAcceptIncoming(); void ThreadI2PAcceptIncoming();
void AcceptConnection(const ListenSocket& hListenSocket); void AcceptConnection(const ListenSocket& hListenSocket);
@ -1005,7 +1006,7 @@ private:
/** /**
* Check connected and listening sockets for IO readiness and process them accordingly. * Check connected and listening sockets for IO readiness and process them accordingly.
*/ */
void SocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex); void SocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !mutexMsgProc);
/** /**
* Do the read/write for connected sockets that are ready for IO. * Do the read/write for connected sockets that are ready for IO.
@ -1019,7 +1020,7 @@ private:
const std::set<SOCKET>& recv_set, const std::set<SOCKET>& recv_set,
const std::set<SOCKET>& send_set, const std::set<SOCKET>& send_set,
const std::set<SOCKET>& error_set) const std::set<SOCKET>& error_set)
EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex); EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !mutexMsgProc);
/** /**
* Accept incoming connections, one from each read-ready listening socket. * Accept incoming connections, one from each read-ready listening socket.
@ -1027,8 +1028,8 @@ private:
*/ */
void SocketHandlerListening(const std::set<SOCKET>& recv_set); void SocketHandlerListening(const std::set<SOCKET>& recv_set);
void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex); void ThreadSocketHandler() EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !mutexMsgProc);
void ThreadDNSAddressSeed(); void ThreadDNSAddressSeed() EXCLUSIVE_LOCKS_REQUIRED(!m_addr_fetches_mutex, !m_nodes_mutex);
uint64_t CalculateKeyedNetGroup(const CAddress& ad) const; uint64_t CalculateKeyedNetGroup(const CAddress& ad) const;

View file

@ -431,30 +431,37 @@ public:
CTxMemPool& pool, bool ignore_incoming_txs); CTxMemPool& pool, bool ignore_incoming_txs);
/** Overridden from CValidationInterface. */ /** Overridden from CValidationInterface. */
void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override; void BlockConnected(const std::shared_ptr<const CBlock>& pblock, const CBlockIndex* pindexConnected) override
void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) override; EXCLUSIVE_LOCKS_REQUIRED(!m_recent_confirmed_transactions_mutex);
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override; void BlockDisconnected(const std::shared_ptr<const CBlock> &block, const CBlockIndex* pindex) override
void BlockChecked(const CBlock& block, const BlockValidationState& state) override; EXCLUSIVE_LOCKS_REQUIRED(!m_recent_confirmed_transactions_mutex);
void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload) override
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void BlockChecked(const CBlock& block, const BlockValidationState& state) override
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override; void NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_ptr<const CBlock>& pblock) override;
/** Implement NetEventsInterface */ /** Implement NetEventsInterface */
void InitializeNode(CNode* pnode) override; void InitializeNode(CNode* pnode) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void FinalizeNode(const CNode& node) override; void FinalizeNode(const CNode& node) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override; bool ProcessMessages(CNode* pfrom, std::atomic<bool>& interrupt) override
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing); EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex);
bool SendMessages(CNode* pto) override EXCLUSIVE_LOCKS_REQUIRED(pto->cs_sendProcessing)
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex);
/** Implement PeerManager */ /** Implement PeerManager */
void StartScheduledTasks(CScheduler& scheduler) override; void StartScheduledTasks(CScheduler& scheduler) override;
void CheckForStaleTipAndEvictPeers() override; void CheckForStaleTipAndEvictPeers() override;
std::optional<std::string> FetchBlock(NodeId peer_id, const CBlockIndex& block_index) override; std::optional<std::string> FetchBlock(NodeId peer_id, const CBlockIndex& block_index) override;
bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override; bool GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) const override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; } bool IgnoresIncomingTxs() override { return m_ignore_incoming_txs; }
void SendPings() override; void SendPings() override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void RelayTransaction(const uint256& txid, const uint256& wtxid) override; void RelayTransaction(const uint256& txid, const uint256& wtxid) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void SetBestHeight(int height) override { m_best_height = height; }; void SetBestHeight(int height) override { m_best_height = height; };
void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) override; void Misbehaving(const NodeId pnode, const int howmuch, const std::string& message) override EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv, void ProcessMessage(CNode& pfrom, const std::string& msg_type, CDataStream& vRecv,
const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) override; const std::chrono::microseconds time_received, const std::atomic<bool>& interruptMsgProc) override
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex, !m_recent_confirmed_transactions_mutex);
void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds) override; void UpdateLastBlockAnnounceTime(NodeId node, int64_t time_in_seconds) override;
private: private:
@ -465,15 +472,15 @@ private:
void EvictExtraOutboundPeers(std::chrono::seconds now) EXCLUSIVE_LOCKS_REQUIRED(cs_main); void EvictExtraOutboundPeers(std::chrono::seconds now) EXCLUSIVE_LOCKS_REQUIRED(cs_main);
/** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */ /** Retrieve unbroadcast transactions from the mempool and reattempt sending to peers */
void ReattemptInitialBroadcast(CScheduler& scheduler); void ReattemptInitialBroadcast(CScheduler& scheduler) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/** Get a shared pointer to the Peer object. /** Get a shared pointer to the Peer object.
* May return an empty shared_ptr if the Peer object can't be found. */ * May return an empty shared_ptr if the Peer object can't be found. */
PeerRef GetPeerRef(NodeId id) const; PeerRef GetPeerRef(NodeId id) const EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/** Get a shared pointer to the Peer object and remove it from m_peer_map. /** Get a shared pointer to the Peer object and remove it from m_peer_map.
* May return an empty shared_ptr if the Peer object can't be found. */ * May return an empty shared_ptr if the Peer object can't be found. */
PeerRef RemovePeer(NodeId id); PeerRef RemovePeer(NodeId id) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/** /**
* Potentially mark a node discouraged based on the contents of a BlockValidationState object * Potentially mark a node discouraged based on the contents of a BlockValidationState object
@ -486,14 +493,16 @@ private:
* @return Returns true if the peer was punished (probably disconnected) * @return Returns true if the peer was punished (probably disconnected)
*/ */
bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state, bool MaybePunishNodeForBlock(NodeId nodeid, const BlockValidationState& state,
bool via_compact_block, const std::string& message = ""); bool via_compact_block, const std::string& message = "")
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/** /**
* Potentially disconnect and discourage a node based on the contents of a TxValidationState object * Potentially disconnect and discourage a node based on the contents of a TxValidationState object
* *
* @return Returns true if the peer was punished (probably disconnected) * @return Returns true if the peer was punished (probably disconnected)
*/ */
bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = ""); bool MaybePunishNodeForTx(NodeId nodeid, const TxValidationState& state, const std::string& message = "")
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/** Maybe disconnect a peer and discourage future connections from its address. /** Maybe disconnect a peer and discourage future connections from its address.
* *
@ -503,13 +512,16 @@ private:
*/ */
bool MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer); bool MaybeDiscourageAndDisconnect(CNode& pnode, Peer& peer);
void ProcessOrphanTx(std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans); void ProcessOrphanTx(std::set<uint256>& orphan_work_set) EXCLUSIVE_LOCKS_REQUIRED(cs_main, g_cs_orphans)
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/** Process a single headers message from a peer. */ /** Process a single headers message from a peer. */
void ProcessHeadersMessage(CNode& pfrom, const Peer& peer, void ProcessHeadersMessage(CNode& pfrom, const Peer& peer,
const std::vector<CBlockHeader>& headers, const std::vector<CBlockHeader>& headers,
bool via_compact_block); bool via_compact_block)
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req); void SendBlockTransactions(CNode& pfrom, const CBlock& block, const BlockTransactionsRequest& req)
EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/** Register with TxRequestTracker that an INV has been received from a /** Register with TxRequestTracker that an INV has been received from a
* peer. The announcement parameters are decided in PeerManager and then * peer. The announcement parameters are decided in PeerManager and then
@ -536,7 +548,7 @@ private:
* @param[in] fReachable Whether the address' network is reachable. We relay unreachable * @param[in] fReachable Whether the address' network is reachable. We relay unreachable
* addresses less. * addresses less.
*/ */
void RelayAddress(NodeId originator, const CAddress& addr, bool fReachable); void RelayAddress(NodeId originator, const CAddress& addr, bool fReachable) EXCLUSIVE_LOCKS_REQUIRED(!m_peer_mutex);
/** Send `feefilter` message. */ /** Send `feefilter` message. */
void MaybeSendFeefilter(CNode& node, Peer& peer, std::chrono::microseconds current_time); void MaybeSendFeefilter(CNode& node, Peer& peer, std::chrono::microseconds current_time);
@ -606,7 +618,8 @@ private:
/** Number of preferable block download peers. */ /** Number of preferable block download peers. */
int m_num_preferred_download_peers GUARDED_BY(cs_main){0}; int m_num_preferred_download_peers GUARDED_BY(cs_main){0};
bool AlreadyHaveTx(const GenTxid& gtxid) EXCLUSIVE_LOCKS_REQUIRED(cs_main); bool AlreadyHaveTx(const GenTxid& gtxid)
EXCLUSIVE_LOCKS_REQUIRED(cs_main, !m_recent_confirmed_transactions_mutex);
/** /**
* Filter for transactions that were recently rejected by the mempool. * Filter for transactions that were recently rejected by the mempool.

View file

@ -61,7 +61,7 @@ public:
//! Return number of connections, default is in- and outbound (total) //! Return number of connections, default is in- and outbound (total)
int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const; int getNumConnections(unsigned int flags = CONNECTIONS_ALL) const;
int getNumBlocks() const; int getNumBlocks() const;
uint256 getBestBlockHash(); uint256 getBestBlockHash() EXCLUSIVE_LOCKS_REQUIRED(!m_cached_tip_mutex);
int getHeaderTipHeight() const; int getHeaderTipHeight() const;
int64_t getHeaderTipTime() const; int64_t getHeaderTipTime() const;

View file

@ -374,7 +374,7 @@ public:
{ {
} }
void AddEvent(uint32_t event_info) noexcept void AddEvent(uint32_t event_info) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_events_mutex)
{ {
LOCK(m_events_mutex); LOCK(m_events_mutex);
@ -388,7 +388,7 @@ public:
/** /**
* Feed (the hash of) all events added through AddEvent() to hasher. * Feed (the hash of) all events added through AddEvent() to hasher.
*/ */
void SeedEvents(CSHA512& hasher) noexcept void SeedEvents(CSHA512& hasher) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_events_mutex)
{ {
// We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256, // We use only SHA256 for the events hashing to get the ASM speedups we have for SHA256,
// since we want it to be fast as network peers may be able to trigger it repeatedly. // since we want it to be fast as network peers may be able to trigger it repeatedly.
@ -407,7 +407,7 @@ public:
* *
* If this function has never been called with strong_seed = true, false is returned. * If this function has never been called with strong_seed = true, false is returned.
*/ */
bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed) noexcept bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed) noexcept EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
assert(num <= 32); assert(num <= 32);
unsigned char buf[64]; unsigned char buf[64];

View file

@ -46,10 +46,10 @@ public:
typedef std::function<void()> Function; typedef std::function<void()> Function;
/** Call func at/after time t */ /** Call func at/after time t */
void schedule(Function f, std::chrono::steady_clock::time_point t); void schedule(Function f, std::chrono::steady_clock::time_point t) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
/** Call f once after the delta has passed */ /** Call f once after the delta has passed */
void scheduleFromNow(Function f, std::chrono::milliseconds delta) void scheduleFromNow(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
{ {
schedule(std::move(f), std::chrono::steady_clock::now() + delta); schedule(std::move(f), std::chrono::steady_clock::now() + delta);
} }
@ -60,29 +60,29 @@ public:
* The timing is not exact: Every time f is finished, it is rescheduled to run again after delta. If you need more * The timing is not exact: Every time f is finished, it is rescheduled to run again after delta. If you need more
* accurate scheduling, don't use this method. * accurate scheduling, don't use this method.
*/ */
void scheduleEvery(Function f, std::chrono::milliseconds delta); void scheduleEvery(Function f, std::chrono::milliseconds delta) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
/** /**
* Mock the scheduler to fast forward in time. * Mock the scheduler to fast forward in time.
* Iterates through items on taskQueue and reschedules them * Iterates through items on taskQueue and reschedules them
* to be delta_seconds sooner. * to be delta_seconds sooner.
*/ */
void MockForward(std::chrono::seconds delta_seconds); void MockForward(std::chrono::seconds delta_seconds) EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
/** /**
* Services the queue 'forever'. Should be run in a thread. * Services the queue 'forever'. Should be run in a thread.
*/ */
void serviceQueue(); void serviceQueue() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
/** Tell any threads running serviceQueue to stop as soon as the current task is done */ /** Tell any threads running serviceQueue to stop as soon as the current task is done */
void stop() void stop() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
{ {
WITH_LOCK(newTaskMutex, stopRequested = true); WITH_LOCK(newTaskMutex, stopRequested = true);
newTaskScheduled.notify_all(); newTaskScheduled.notify_all();
if (m_service_thread.joinable()) m_service_thread.join(); if (m_service_thread.joinable()) m_service_thread.join();
} }
/** Tell any threads running serviceQueue to stop when there is no work left to be done */ /** Tell any threads running serviceQueue to stop when there is no work left to be done */
void StopWhenDrained() void StopWhenDrained() EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex)
{ {
WITH_LOCK(newTaskMutex, stopWhenEmpty = true); WITH_LOCK(newTaskMutex, stopWhenEmpty = true);
newTaskScheduled.notify_all(); newTaskScheduled.notify_all();
@ -94,10 +94,11 @@ public:
* and first and last task times * and first and last task times
*/ */
size_t getQueueInfo(std::chrono::steady_clock::time_point& first, size_t getQueueInfo(std::chrono::steady_clock::time_point& first,
std::chrono::steady_clock::time_point& last) const; std::chrono::steady_clock::time_point& last) const
EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
/** Returns true if there are threads actively running in serviceQueue() */ /** Returns true if there are threads actively running in serviceQueue() */
bool AreThreadsServicingQueue() const; bool AreThreadsServicingQueue() const EXCLUSIVE_LOCKS_REQUIRED(!newTaskMutex);
private: private:
mutable Mutex newTaskMutex; mutable Mutex newTaskMutex;
@ -128,8 +129,8 @@ private:
std::list<std::function<void()>> m_callbacks_pending GUARDED_BY(m_callbacks_mutex); std::list<std::function<void()>> m_callbacks_pending GUARDED_BY(m_callbacks_mutex);
bool m_are_callbacks_running GUARDED_BY(m_callbacks_mutex) = false; bool m_are_callbacks_running GUARDED_BY(m_callbacks_mutex) = false;
void MaybeScheduleProcessQueue(); void MaybeScheduleProcessQueue() EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex);
void ProcessQueue(); void ProcessQueue() EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex);
public: public:
explicit SingleThreadedSchedulerClient(CScheduler& scheduler LIFETIMEBOUND) : m_scheduler{scheduler} {} explicit SingleThreadedSchedulerClient(CScheduler& scheduler LIFETIMEBOUND) : m_scheduler{scheduler} {}
@ -140,15 +141,15 @@ public:
* Practically, this means that callbacks can behave as if they are executed * Practically, this means that callbacks can behave as if they are executed
* in order by a single thread. * in order by a single thread.
*/ */
void AddToProcessQueue(std::function<void()> func); void AddToProcessQueue(std::function<void()> func) EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex);
/** /**
* Processes all remaining queue members on the calling thread, blocking until queue is empty * Processes all remaining queue members on the calling thread, blocking until queue is empty
* Must be called after the CScheduler has no remaining processing threads! * Must be called after the CScheduler has no remaining processing threads!
*/ */
void EmptyQueue(); void EmptyQueue() EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex);
size_t CallbacksPending(); size_t CallbacksPending() EXCLUSIVE_LOCKS_REQUIRED(!m_callbacks_mutex);
}; };
#endif // BITCOIN_SCHEDULER_H #endif // BITCOIN_SCHEDULER_H

View file

@ -83,8 +83,6 @@ void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLi
inline void DeleteLock(void* cs) {} inline void DeleteLock(void* cs) {}
inline bool LockStackEmpty() { return true; } inline bool LockStackEmpty() { return true; }
#endif #endif
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
#define AssertLockNotHeld(cs) AssertLockNotHeldInternal(#cs, __FILE__, __LINE__, &cs)
/** /**
* Template mixin that adds -Wthread-safety locking annotations and lock order * Template mixin that adds -Wthread-safety locking annotations and lock order
@ -129,7 +127,13 @@ public:
using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>; using RecursiveMutex = AnnotatedMixin<std::recursive_mutex>;
/** Wrapped mutex: supports waiting but not recursive locking */ /** Wrapped mutex: supports waiting but not recursive locking */
typedef AnnotatedMixin<std::mutex> Mutex; using Mutex = AnnotatedMixin<std::mutex>;
#define AssertLockHeld(cs) AssertLockHeldInternal(#cs, __FILE__, __LINE__, &cs)
inline void AssertLockNotHeldInline(const char* name, const char* file, int line, Mutex* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) { AssertLockNotHeldInternal(name, file, line, cs); }
inline void AssertLockNotHeldInline(const char* name, const char* file, int line, RecursiveMutex* cs) LOCKS_EXCLUDED(cs) { AssertLockNotHeldInternal(name, file, line, cs); }
#define AssertLockNotHeld(cs) AssertLockNotHeldInline(#cs, __FILE__, __LINE__, &cs)
/** Wrapper around std::unique_lock style lock for Mutex. */ /** Wrapper around std::unique_lock style lock for Mutex. */
template <typename Mutex, typename Base = typename Mutex::UniqueLock> template <typename Mutex, typename Base = typename Mutex::UniqueLock>

View file

@ -21,11 +21,11 @@ class CThreadInterrupt
public: public:
CThreadInterrupt(); CThreadInterrupt();
explicit operator bool() const; explicit operator bool() const;
void operator()(); void operator()() EXCLUSIVE_LOCKS_REQUIRED(!mut);
void reset(); void reset();
bool sleep_for(std::chrono::milliseconds rel_time); bool sleep_for(std::chrono::milliseconds rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut);
bool sleep_for(std::chrono::seconds rel_time); bool sleep_for(std::chrono::seconds rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut);
bool sleep_for(std::chrono::minutes rel_time); bool sleep_for(std::chrono::minutes rel_time) EXCLUSIVE_LOCKS_REQUIRED(!mut);
private: private:
std::condition_variable cond; std::condition_variable cond;

View file

@ -44,7 +44,7 @@ public:
explicit MainSignalsImpl(CScheduler& scheduler LIFETIMEBOUND) : m_schedulerClient(scheduler) {} explicit MainSignalsImpl(CScheduler& scheduler LIFETIMEBOUND) : m_schedulerClient(scheduler) {}
void Register(std::shared_ptr<CValidationInterface> callbacks) void Register(std::shared_ptr<CValidationInterface> callbacks) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
LOCK(m_mutex); LOCK(m_mutex);
auto inserted = m_map.emplace(callbacks.get(), m_list.end()); auto inserted = m_map.emplace(callbacks.get(), m_list.end());
@ -52,7 +52,7 @@ public:
inserted.first->second->callbacks = std::move(callbacks); inserted.first->second->callbacks = std::move(callbacks);
} }
void Unregister(CValidationInterface* callbacks) void Unregister(CValidationInterface* callbacks) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
LOCK(m_mutex); LOCK(m_mutex);
auto it = m_map.find(callbacks); auto it = m_map.find(callbacks);
@ -66,7 +66,7 @@ public:
//! map entry. After this call, the list may still contain callbacks that //! map entry. After this call, the list may still contain callbacks that
//! are currently executing, but it will be cleared when they are done //! are currently executing, but it will be cleared when they are done
//! executing. //! executing.
void Clear() void Clear() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
LOCK(m_mutex); LOCK(m_mutex);
for (const auto& entry : m_map) { for (const auto& entry : m_map) {
@ -75,7 +75,7 @@ public:
m_map.clear(); m_map.clear();
} }
template<typename F> void Iterate(F&& f) template<typename F> void Iterate(F&& f) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex)
{ {
WAIT_LOCK(m_mutex, lock); WAIT_LOCK(m_mutex, lock);
for (auto it = m_list.begin(); it != m_list.end();) { for (auto it = m_list.begin(); it != m_list.end();) {

View file

@ -92,16 +92,16 @@ public:
static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos); static uint32_t Mask(const Consensus::Params& params, Consensus::DeploymentPos pos);
/** Get the BIP9 state for a given deployment for the block after pindexPrev. */ /** Get the BIP9 state for a given deployment for the block after pindexPrev. */
ThresholdState State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos); ThresholdState State(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
/** Get the block height at which the BIP9 deployment switched into the state for the block after pindexPrev. */ /** Get the block height at which the BIP9 deployment switched into the state for the block after pindexPrev. */
int StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos); int StateSinceHeight(const CBlockIndex* pindexPrev, const Consensus::Params& params, Consensus::DeploymentPos pos) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
/** Determine what nVersion a new block should use /** Determine what nVersion a new block should use
*/ */
int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params); int32_t ComputeBlockVersion(const CBlockIndex* pindexPrev, const Consensus::Params& params) EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
void Clear(); void Clear() EXCLUSIVE_LOCKS_REQUIRED(!m_mutex);
}; };
#endif // BITCOIN_VERSIONBITS_H #endif // BITCOIN_VERSIONBITS_H