New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
JDK-8275704: Metaspace::contains() should be threadsafe #6060
JDK-8275704: Metaspace::contains() should be threadsafe #6060
Conversation
|
7ddf71e
to
bfe54c1
Compare
Webrevs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good! Thank you for fixing this.
@tstuefe This change now passes all automated pre-integration checks. After integration, the commit message for the final commit will be:
You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 12 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.
|
Thank you Coleen! |
@@ -186,7 +189,8 @@ void VirtualSpaceList::verify() const { | |||
|
|||
// Returns true if this pointer is contained in one of our nodes. | |||
bool VirtualSpaceList::contains(const MetaWord* p) const { | |||
const VirtualSpaceNode* vsn = _first_node; | |||
// Note: needs to work without locks. | |||
const VirtualSpaceNode* vsn = Atomic::load_acquire(&_first_node); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe vsn->next() now also requires load_acquire semantics.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The internal nodes are already protected by the acquire/release semantics used for accessing _first_node
, which is the only mutable field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's what I figured too.
Also, if that were wrong we would have the same problem in CLDG. Where, in contrast to this list nodes get deleted too (see ClassLoaderDataGraph::clear_claimed_marks()).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Thomas,
This seems fine to me.
Thanks,
David
@@ -186,7 +189,8 @@ void VirtualSpaceList::verify() const { | |||
|
|||
// Returns true if this pointer is contained in one of our nodes. | |||
bool VirtualSpaceList::contains(const MetaWord* p) const { | |||
const VirtualSpaceNode* vsn = _first_node; | |||
// Note: needs to work without locks. | |||
const VirtualSpaceNode* vsn = Atomic::load_acquire(&_first_node); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The internal nodes are already protected by the acquire/release semantics used for accessing _first_node
, which is the only mutable field.
// never to be destroyed. | ||
// | ||
// The list will only be modified under lock protection, but may be | ||
// read asynchronously without lock. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
asynchronously? Did you mean concurrently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I'll correct it before pushing.
Thanks @coleenp, @zhengyu123, @dholmes-ora! Note that one of the next changes will be an increase in size of the individual mappings. Today they are two root chunks sized (8MB) and by making them bigger we will have fewer of them, which will make traversing the list in /integrate |
Going to push as commit d9b0138.
Your commit was automatically rebased without conflicts. |
Metaspace::contains() is used in many places. It is not threadsafe since it walks the list of metaspace mappings, which can be altered concurrently. This is suspected to be the cause of JDK-8271124.
Currently, it does not lock, and adding a lock is not realistic either. It should work lockless.
This patch builds atop of https://bugs.openjdk.java.net/browse/JDK-8275582, which removed the old (pre JEP 387) technique of uncommitting metaspace memory. As a side effect, that patch changed the mapping list to an add-only structure. The only remaining place where it gets modified is in VirtualSpaceList::create_node(). Modifications are synchronized via lock. The only place where we walk the list locklessly is in Metaspace::contains(). This patch adds the appropriate memory barriers to those two places.
Tests:
Progress
Issue
Reviewers
Reviewing
Using
git
Checkout this PR locally:
$ git fetch https://git.openjdk.java.net/jdk pull/6060/head:pull/6060
$ git checkout pull/6060
Update a local copy of the PR:
$ git checkout pull/6060
$ git pull https://git.openjdk.java.net/jdk pull/6060/head
Using Skara CLI tools
Checkout this PR locally:
$ git pr checkout 6060
View PR using the GUI difftool:
$ git pr show -t 6060
Using diff file
Download this PR as a diff file:
https://git.openjdk.java.net/jdk/pull/6060.diff