Skip to content

Commit f942c07

Browse files
committed
sync: use proper TSA attributes
Use the proper attribute from Clang's thread safety analysis for `AssertLockHeld()`: * if `DEBUG_LOCKORDER` is defined then `AssertLockHeld()` will check if the caller owns the given mutex and will `abort()` if not. Clang has an attribute exactly for that - `ASSERT_EXCLUSIVE_LOCK()`, documented as: "These are attributes on a function or method that does a run-time test to see whether the calling thread holds the given capability. The function is assumed to fail (no return) if the capability is not held." [1] * if `DEBUG_LOCKORDER` is not defined, then `AssertLockHeld()` does nothing, thus don't tag it with any attributes (don't fool the compiler that we do something which we don't). Replace `LockAssertion` with `AssertLockHeld` and remove the former. On the places where Clang cannot deduce that a mutex is held, use `NO_THREAD_SAFETY_ANALYSIS`, intended to be used when a code is "too complicated for the analysis to understand" [2]. [1] https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#requires-requires-shared [2] https://clang.llvm.org/docs/ThreadSafetyAnalysis.html#no-thread-safety-analysis
1 parent 564e1ab commit f942c07

File tree

2 files changed

+15
-29
lines changed

2 files changed

+15
-29
lines changed

src/net_processing.cpp

+11-11
Original file line numberDiff line numberDiff line change
@@ -662,8 +662,8 @@ static void MaybeSetPeerAsAnnouncingHeaderAndIDs(NodeId nodeid, CConnman& connma
662662
return;
663663
}
664664
}
665-
connman.ForNode(nodeid, [&connman](CNode* pfrom){
666-
LockAssertion lock(::cs_main);
665+
connman.ForNode(nodeid, [&connman](CNode* pfrom) NO_THREAD_SAFETY_ANALYSIS {
666+
AssertLockHeld(::cs_main);
667667
uint64_t nCMPCTBLOCKVersion = (pfrom->GetLocalServices() & NODE_WITNESS) ? 2 : 1;
668668
if (lNodesAnnouncingHeaderAndIDs.size() >= 3) {
669669
// As per BIP152, we only get 3 of our peers to announce
@@ -1354,8 +1354,9 @@ void PeerManager::NewPoWValidBlock(const CBlockIndex *pindex, const std::shared_
13541354
fWitnessesPresentInMostRecentCompactBlock = fWitnessEnabled;
13551355
}
13561356

1357-
m_connman.ForEachNode([this, &pcmpctblock, pindex, &msgMaker, fWitnessEnabled, &hashBlock](CNode* pnode) {
1358-
LockAssertion lock(::cs_main);
1357+
m_connman.ForEachNode([this, &pcmpctblock, pindex, &msgMaker, fWitnessEnabled,
1358+
&hashBlock](CNode* pnode) NO_THREAD_SAFETY_ANALYSIS {
1359+
AssertLockHeld(::cs_main);
13591360

13601361
// TODO: Avoid the repeated-serialization here
13611362
if (pnode->nVersion < INVALID_CB_NO_BAN_VERSION || pnode->fDisconnect)
@@ -1488,9 +1489,8 @@ bool static AlreadyHaveBlock(const uint256& block_hash) EXCLUSIVE_LOCKS_REQUIRED
14881489

14891490
void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman& connman)
14901491
{
1491-
connman.ForEachNode([&txid, &wtxid](CNode* pnode)
1492-
{
1493-
LockAssertion lock(::cs_main);
1492+
connman.ForEachNode([&txid, &wtxid](CNode* pnode) NO_THREAD_SAFETY_ANALYSIS {
1493+
AssertLockHeld(::cs_main);
14941494

14951495
CNodeState &state = *State(pnode->GetId());
14961496
if (state.m_wtxid_relay) {
@@ -3979,8 +3979,8 @@ void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds)
39793979
NodeId worst_peer = -1;
39803980
int64_t oldest_block_announcement = std::numeric_limits<int64_t>::max();
39813981

3982-
m_connman.ForEachNode([&](CNode* pnode) {
3983-
LockAssertion lock(::cs_main);
3982+
m_connman.ForEachNode([&](CNode* pnode) NO_THREAD_SAFETY_ANALYSIS {
3983+
AssertLockHeld(::cs_main);
39843984

39853985
// Ignore non-outbound peers, or nodes marked for disconnect already
39863986
if (!pnode->IsOutboundOrBlockRelayConn() || pnode->fDisconnect) return;
@@ -3996,8 +3996,8 @@ void PeerManager::EvictExtraOutboundPeers(int64_t time_in_seconds)
39963996
}
39973997
});
39983998
if (worst_peer != -1) {
3999-
bool disconnected = m_connman.ForNode(worst_peer, [&](CNode *pnode) {
4000-
LockAssertion lock(::cs_main);
3999+
bool disconnected = m_connman.ForNode(worst_peer, [&](CNode *pnode) NO_THREAD_SAFETY_ANALYSIS {
4000+
AssertLockHeld(::cs_main);
40014001

40024002
// Only disconnect a peer that has been connected to us for
40034003
// some reasonable fraction of our check-frequency, to give

src/sync.h

+4-18
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ void LeaveCritical();
5353
void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line);
5454
std::string LocksHeld();
5555
template <typename MutexType>
56-
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs);
56+
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) ASSERT_EXCLUSIVE_LOCK(cs);
5757
template <typename MutexType>
58-
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs);
58+
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) ASSERT_EXCLUSIVE_LOCK(!cs);
5959
void DeleteLock(void* cs);
6060
bool LockStackEmpty();
6161

@@ -70,9 +70,9 @@ inline void EnterCritical(const char* pszName, const char* pszFile, int nLine, v
7070
inline void LeaveCritical() {}
7171
inline void CheckLastCritical(void* cs, std::string& lockname, const char* guardname, const char* file, int line) {}
7272
template <typename MutexType>
73-
inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(cs) {}
73+
inline void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) {}
7474
template <typename MutexType>
75-
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) EXCLUSIVE_LOCKS_REQUIRED(!cs) {}
75+
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs) {}
7676
inline void DeleteLock(void* cs) {}
7777
inline bool LockStackEmpty() { return true; }
7878
#endif
@@ -352,18 +352,4 @@ class CSemaphoreGrant
352352
}
353353
};
354354

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-
explicit LockAssertion(Mutex& mutex) EXCLUSIVE_LOCK_FUNCTION(mutex)
361-
{
362-
#ifdef DEBUG_LOCKORDER
363-
AssertLockHeld(mutex);
364-
#endif
365-
}
366-
~LockAssertion() UNLOCK_FUNCTION() {}
367-
};
368-
369355
#endif // BITCOIN_SYNC_H

0 commit comments

Comments
 (0)