8275704: Metaspace::contains() should be threadsafe

Reviewed-by: coleenp, dholmes
This commit is contained in:
Thomas Stuefe 2021-10-28 05:29:58 +00:00
parent 9a3e954299
commit d9b0138d7d
2 changed files with 22 additions and 8 deletions

View File

@ -34,6 +34,7 @@
#include "memory/metaspace/metaspaceCommon.hpp"
#include "memory/metaspace/virtualSpaceList.hpp"
#include "memory/metaspace/virtualSpaceNode.hpp"
#include "runtime/atomic.hpp"
#include "runtime/mutexLocker.hpp"
namespace metaspace {
@ -74,8 +75,10 @@ VirtualSpaceList::VirtualSpaceList(const char* name, ReservedSpace rs, CommitLim
VirtualSpaceList::~VirtualSpaceList() {
assert_lock_strong(Metaspace_lock);
// Note: normally, there is no reason ever to delete a vslist since they are
// global objects, but for gtests it makes sense to allow this.
// Delete every single mapping in this list.
// Please note that this only gets executed during gtests under controlled
// circumstances, so we do not have any concurrency issues here. The "real"
// lists in metaspace are immortal.
VirtualSpaceNode* vsn = _first_node;
VirtualSpaceNode* vsn2 = vsn;
while (vsn != NULL) {
@ -96,7 +99,7 @@ void VirtualSpaceList::create_new_node() {
_commit_limiter,
&_reserved_words_counter, &_committed_words_counter);
vsn->set_next(_first_node);
_first_node = vsn;
Atomic::release_store(&_first_node, vsn);
_nodes_counter.increment();
}
@ -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);
while (vsn != NULL) {
if (vsn->contains(p)) {
return true;

View File

@ -40,22 +40,32 @@ namespace metaspace {
class Metachunk;
class FreeChunkListVector;
// VirtualSpaceList manages a single (if its non-expandable) or
// a series of (if its expandable) virtual memory regions used
// VirtualSpaceList manages a series of virtual memory regions used
// for metaspace.
//
// Internally it holds a list of nodes (VirtualSpaceNode) each
// managing a single contiguous memory region. The first node of
// this list is the current node and used for allocation of new
// root chunks.
//
// The list will only ever grow, never shrink. It will be immortal,
// never to be destroyed.
//
// The list will only be modified under lock protection, but may be
// read concurrently without lock.
//
// The list may be prevented from expanding beyond a single node -
// in that case it degenerates to a one-node-list (used for
// class space).
//
class VirtualSpaceList : public CHeapObj<mtClass> {
// Name
const char* const _name;
// Head of the list.
VirtualSpaceNode* _first_node;
// Head of the list (last added).
VirtualSpaceNode* volatile _first_node;
// Number of nodes (kept for statistics only).
IntCounter _nodes_counter;