Skip to content

Conversation

@ajtowns
Copy link
Contributor

@ajtowns ajtowns commented Jan 29, 2020

Splits the epoch logic introduced in #17925 into a separate class.

Uses clang's thread safety annotations and encapsulates the data more strongly to reduce chances of bugs from API misuse.

@JeremyRubin
Copy link
Contributor

Concept ACK. Will need to play around with it a little bit to test that clang actually prevents compiling incorrect uses.

@DrahtBot
Copy link
Contributor

DrahtBot commented Jan 29, 2020

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

No conflicts as of last run.

@ajtowns ajtowns marked this pull request as ready for review February 3, 2020 12:56
@laanwj
Copy link
Member

laanwj commented Feb 10, 2020

Concept ACK, nice

@hebasto
Copy link
Member

hebasto commented May 24, 2020

Concept ACK.

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A brilliant idea to leverage the Clang Thread Safety Analysis!

@ajtowns
Copy link
Contributor Author

ajtowns commented May 26, 2020

Incorporated @hebasto's suggested changes

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 837d4e4f5aeb2f110143c59b7dd05eac6ae52b63, tested on Linux Mint 19.3: the Clang's thread safety annotations indeed reduce chances of the Epoch class misuse (verified by different code manipulations).

May I suggest two additional annotations:

--- a/src/txmempool.cpp
+++ b/src/txmempool.cpp
@@ -107,6 +107,7 @@ void CTxMemPool::UpdateForDescendants(txiter updateIt, cacheMap &cachedDescendan
 void CTxMemPool::UpdateTransactionsFromBlock(const std::vector<uint256> &vHashesToUpdate)
 {
     AssertLockHeld(cs);
+    AssertLockNotHeld(m_epoch);
     // For each entry in vHashesToUpdate, store the set of in-mempool, but not
     // in-vHashesToUpdate transactions, so that we don't have to recalculate
     // descendants when we come across a previously seen entry.
diff --git a/src/txmempool.h b/src/txmempool.h
index 655afc3b8..b72ad229c 100644
--- a/src/txmempool.h
+++ b/src/txmempool.h
@@ -797,7 +797,7 @@ private:
      */
     void UpdateForDescendants(txiter updateIt,
             cacheMap &cachedDescendants,
-            const std::set<uint256> &setExclude) EXCLUSIVE_LOCKS_REQUIRED(cs);
+            const std::set<uint256> &setExclude) EXCLUSIVE_LOCKS_REQUIRED(cs) LOCKS_EXCLUDED(m_epoch);
     /** Update ancestors of hash to add/remove it as a descendant transaction. */
     void UpdateAncestorsOf(bool add, txiter hash, setEntries &setAncestors) EXCLUSIVE_LOCKS_REQUIRED(cs);
     /** Set ancestor state for an entry */

?

@ajtowns
Copy link
Contributor Author

ajtowns commented May 26, 2020

@hebasto - AssertLockNotHeld(m_epoch) won't work -- epochs aren't sync.h locks. I think the annotation for UpdateForDescendents would be better made after #18191 is merged?

@hebasto
Copy link
Member

hebasto commented May 26, 2020

@ajtowns

@hebasto - AssertLockNotHeld(m_epoch) won't work -- epochs aren't sync.h locks. I think the annotation for UpdateForDescendents would be better made after #18191 is merged?

Agree.

@ajtowns
Copy link
Contributor Author

ajtowns commented Sep 10, 2020

Rebased

@ajtowns
Copy link
Contributor Author

ajtowns commented Jan 14, 2021

Rebased to deal with adjacent lines changed in #19935

Copy link

@felipsoarez felipsoarez left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

utACK

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK 88019f9a183d396713fd357604a6e472c5ed8807

It seems both CTxMemPool::visited member functions could be private.

@ajtowns
Copy link
Contributor Author

ajtowns commented Feb 9, 2021

🎂 This PR turned 1 the other week! Rebased on top of #20944 due to header reordering, and addressed @hebasto's nits.

(I think the mempool visited methods are public deliberately, so that they could be used by external functions if desired; so haven't made them private)

@JeremyRubin
Copy link
Contributor

Yes this is correct; IIRC there's some stalled out patches which require them to be visible :)

Copy link
Member

@jonatack jonatack left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ACK fd6580e using clang thread safety annotations looks like a very good idea, and the encapsulation this change adds should improve robustness (and possible unit test-ability) of the code. Verified that changing some of the locking duly provoked build-time warnings with Clang 9 on Debian and that small changes in the new Epoch class were covered by failing functional test assertions in mempool_updatefromblock.py, mempool_resurrect.py, and mempool_reorg.py

example clang warning

/txmempool.h:840:24: warning: calling function 'visited' requires holding mutex 'm_epoch' exclusively [-Wthread-safety-analysis]
        return m_epoch.visited(it->m_epoch_marker);

Ignore the two comments below unless you need to retouch anything (the documentation was move-only anyway).

* adds an asymptotic factor of O(log n) to traversals cost and triggers O(n)
* more dynamic memory allocations.
* In many algorithms we can replace std::set with an internal mempool
* counter to track the time (or, "epoch") that we began a traversal, and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* counter to track the time (or, "epoch") that we began a traversal, and
* counter to track the time (or, "epoch") that we began a traversal and

* Algorithms using std::set can be replaced on a one by one basis.
* Both techniques are not fundamentally incompatible across the codebase.
* Generally speaking, however, the remaining use of std::set for mempool
* traversal should be viewed as a TODO for replacement with an epoch based
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* traversal should be viewed as a TODO for replacement with an epoch based
* traversal should be viewed as a TODO for replacement with an epoch-based

Copy link
Member

@hebasto hebasto left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

re-ACK fd6580e, since my previous review:

  • rebased
  • style nits and typo addressed
  • added assert(m_epoch.m_guarded); as suggested
  • the Epoch ctor is default now (was empty)

@laanwj laanwj merged commit b59f278 into bitcoin:master Feb 24, 2021
sidhujag pushed a commit to syscoin/syscoin that referenced this pull request Feb 24, 2021
Fabcien pushed a commit to Bitcoin-ABC/bitcoin-abc that referenced this pull request Apr 6, 2022
Summary: This is a backport of [[bitcoin/bitcoin#18017 | core#18017]]

Test Plan:
With clang and  debug:
`ninja all check-all`

Reviewers: #bitcoin_abc, Fabien

Reviewed By: #bitcoin_abc, Fabien

Subscribers: Fabien

Differential Revision: https://reviews.bitcoinabc.org/D11308
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Aug 16, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants