Skip to content

Commit 462b1df

Browse files
committed
8307106: Allow concurrent GCs to walk CLDG without ClassLoaderDataGraph_lock
Reviewed-by: stefank, aboldtch, coleenp, dholmes
1 parent c8f3756 commit 462b1df

File tree

4 files changed

+16
-20
lines changed

4 files changed

+16
-20
lines changed

src/hotspot/share/classfile/classLoaderData.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ class ClassLoaderData : public CHeapObj<mtClass> {
160160
Symbol* _name_and_id;
161161
JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
162162

163-
void set_next(ClassLoaderData* next) { _next = next; }
163+
void set_next(ClassLoaderData* next) { Atomic::store(&_next, next); }
164164
ClassLoaderData* next() const { return Atomic::load(&_next); }
165165

166166
ClassLoaderData(Handle h_class_loader, bool has_class_mirror_holder);

src/hotspot/share/classfile/classLoaderDataGraph.cpp

+15-7
Original file line numberDiff line numberDiff line change
@@ -261,8 +261,15 @@ ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool has_class_mirror_
261261
return loader_data;
262262
}
263263

264+
inline void assert_is_safepoint_or_gc() {
265+
assert(SafepointSynchronize::is_at_safepoint() ||
266+
Thread::current()->is_ConcurrentGC_thread() ||
267+
Thread::current()->is_Worker_thread(),
268+
"Must be called by safepoint or GC");
269+
}
270+
264271
void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
265-
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
272+
assert_is_safepoint_or_gc();
266273
for (ClassLoaderData* cld = _unloading; cld != nullptr; cld = cld->next()) {
267274
assert(cld->is_unloading(), "invariant");
268275
cl->do_cld(cld);
@@ -272,15 +279,15 @@ void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
272279
// These are functions called by the GC, which require all of the CLDs, including the
273280
// unloading ones.
274281
void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
275-
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
276-
for (ClassLoaderData* cld = _head; cld != nullptr; cld = cld->_next) {
282+
assert_is_safepoint_or_gc();
283+
for (ClassLoaderData* cld = Atomic::load_acquire(&_head); cld != nullptr; cld = cld->next()) {
277284
cl->do_cld(cld);
278285
}
279286
}
280287

281288
void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
282-
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
283-
for (ClassLoaderData* cld = _head; cld != nullptr; cld = cld->_next) {
289+
assert_is_safepoint_or_gc();
290+
for (ClassLoaderData* cld = Atomic::load_acquire(&_head); cld != nullptr; cld = cld->next()) {
284291
CLDClosure* closure = cld->keep_alive() ? strong : weak;
285292
if (closure != nullptr) {
286293
closure->do_cld(cld);
@@ -289,7 +296,7 @@ void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
289296
}
290297

291298
void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
292-
assert_locked_or_safepoint_weak(ClassLoaderDataGraph_lock);
299+
assert_is_safepoint_or_gc();
293300
if (ClassUnloading) {
294301
roots_cld_do(cl, nullptr);
295302
} else {
@@ -520,7 +527,8 @@ bool ClassLoaderDataGraph::do_unloading() {
520527
prev->set_next(data);
521528
} else {
522529
assert(dead == _head, "sanity check");
523-
_head = data;
530+
// The GC might be walking this concurrently
531+
Atomic::store(&_head, data);
524532
}
525533
dead->set_next(_unloading);
526534
_unloading = dead;

src/hotspot/share/runtime/mutexLocker.cpp

-10
Original file line numberDiff line numberDiff line change
@@ -175,16 +175,6 @@ void assert_locked_or_safepoint(const Mutex* lock) {
175175
fatal("must own lock %s", lock->name());
176176
}
177177

178-
// a weaker assertion than the above
179-
void assert_locked_or_safepoint_weak(const Mutex* lock) {
180-
if (DebuggingContext::is_enabled() || VMError::is_error_reported()) return;
181-
assert(lock != nullptr, "Need non-null lock");
182-
if (lock->is_locked()) return;
183-
if (SafepointSynchronize::is_at_safepoint()) return;
184-
if (!Universe::is_fully_initialized()) return;
185-
fatal("must own lock %s", lock->name());
186-
}
187-
188178
// a stronger assertion than the above
189179
void assert_lock_strong(const Mutex* lock) {
190180
if (DebuggingContext::is_enabled() || VMError::is_error_reported()) return;

src/hotspot/share/runtime/mutexLocker.hpp

-2
Original file line numberDiff line numberDiff line change
@@ -181,11 +181,9 @@ void print_lock_ranks(outputStream* st);
181181
// for debugging: check that we're already owning this lock (or are at a safepoint / handshake)
182182
#ifdef ASSERT
183183
void assert_locked_or_safepoint(const Mutex* lock);
184-
void assert_locked_or_safepoint_weak(const Mutex* lock);
185184
void assert_lock_strong(const Mutex* lock);
186185
#else
187186
#define assert_locked_or_safepoint(lock)
188-
#define assert_locked_or_safepoint_weak(lock)
189187
#define assert_lock_strong(lock)
190188
#endif
191189

0 commit comments

Comments
 (0)