@@ -1262,11 +1262,18 @@ void ShenandoahHeap::evacuate_collection_set(bool concurrent) {
12621262}
12631263
12641264void ShenandoahHeap::concurrent_prepare_for_update_refs () {
1265- // It's possible that evacuation succeeded, but we could still be cancelled when we get here.
1266- // A cancellation at this point means the degenerated cycle must resume from update-refs.
1267- set_gc_state_concurrent (EVACUATION, false );
1268- set_gc_state_concurrent (WEAK_ROOTS, false );
1269- set_gc_state_concurrent (UPDATE_REFS, true );
1265+ {
1266+ // Java threads take this lock while they are being attached and added to the list of thread.
1267+ // If another thread holds this lock before we update the gc state, it will receive a stale
1268+ // gc state, but they will have been added to the list of java threads and so will be corrected
1269+ // by the following handshake.
1270+ MutexLocker lock (Threads_lock);
1271+
1272+ // A cancellation at this point means the degenerated cycle must resume from update-refs.
1273+ set_gc_state_concurrent (EVACUATION, false );
1274+ set_gc_state_concurrent (WEAK_ROOTS, false );
1275+ set_gc_state_concurrent (UPDATE_REFS, true );
1276+ }
12701277
12711278 // This will propagate the gc state and retire gclabs and plabs for threads that require it.
12721279 ShenandoahPrepareForUpdateRefs prepare_for_update_refs (_gc_state.raw_value ());
@@ -2025,6 +2032,12 @@ void ShenandoahHeap::set_gc_state_at_safepoint(uint mask, bool value) {
20252032}
20262033
20272034void ShenandoahHeap::set_gc_state_concurrent (uint mask, bool value) {
2035+ // Holding the thread lock here assures that any thread created after we change the gc
2036+ // state will have the correct state. It also prevents attaching threads from seeing
2037+ // an inconsistent state. See ShenandoahBarrierSet::on_thread_attach for reference. Established
2038+ // threads will use their thread local copy of the gc state (changed by a handshake, or on a
2039+ // safepoint).
2040+ assert (Threads_lock->is_locked (), " Must hold thread lock for concurrent gc state change" );
20282041 _gc_state.set_cond (mask, value);
20292042}
20302043
0 commit comments