Projects
Mega:24.03:SP1:Everything
openjdk-1.8.0
_service:tar_scm:Backport-8210706-G1-may-deadlo...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:tar_scm:Backport-8210706-G1-may-deadlock-when-starting-a-concurrent-c.patch of Package openjdk-1.8.0
From 8e53927b6739a935dc833f7e9527dacb71bae1a8 Mon Sep 17 00:00:00 2001 Date: Thu, 30 May 2024 07:02:40 +0000 Subject: [PATCH] [Backport]8210706: G1 may deadlock when starting a concurrent cycle at shutdown --- .../gc_implementation/g1/concurrentMark.cpp | 20 +++++++++++-------- .../gc_implementation/g1/concurrentMark.hpp | 4 ++++ .../g1/concurrentMarkThread.cpp | 8 +++++++- .../gc_implementation/g1/g1CollectedHeap.cpp | 14 +++++++------ .../shared/concurrentGCThread.hpp | 2 ++ 5 files changed, 33 insertions(+), 15 deletions(-) diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 1347a7e16..cad474b83 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -477,6 +477,16 @@ HeapRegion* CMRootRegions::claim_next() { return res; } +void CMRootRegions::notify_scan_done() { + MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag); + _scan_in_progress = false; + RootRegionScan_lock->notify_all(); +} + +void CMRootRegions::cancel_scan() { + notify_scan_done(); +} + void CMRootRegions::scan_finished() { assert(scan_in_progress(), "pre-condition"); @@ -486,11 +496,7 @@ void CMRootRegions::scan_finished() { } _next_survivor = NULL; - { - MutexLockerEx x(RootRegionScan_lock, Mutex::_no_safepoint_check_flag); - _scan_in_progress = false; - RootRegionScan_lock->notify_all(); - } + notify_scan_done(); } bool CMRootRegions::wait_until_scan_finished() { @@ -1224,13 +1230,11 @@ public: }; void ConcurrentMark::scanRootRegions() { - // Start of concurrent marking. - ClassLoaderDataGraph::clear_claimed_marks(); - // scan_in_progress() will have been set to true only if there was // at least one root region to scan. So, if it's false, we // should not attempt to do any further work. if (root_regions()->scan_in_progress()) { + assert(!has_aborted(), "Aborting before root region scanning is finished not supported."); _parallel_marking_threads = calc_parallel_marking_threads(); assert(parallel_marking_threads() <= max_parallel_marking_threads(), "Maximum number of marking threads exceeded"); diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp index bbd5d590a..172caef29 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp @@ -333,6 +333,8 @@ private: volatile bool _should_abort; HeapRegion* volatile _next_survivor; + void notify_scan_done(); + public: CMRootRegions(); // We actually do most of the initialization in this method. @@ -352,6 +354,8 @@ public: // all have been claimed. HeapRegion* claim_next(); + void cancel_scan(); + // Flag that we're done with root region scanning and notify anyone // who's waiting on it. If aborted is false, assume that all regions // have been claimed. diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp index 9b0452f92..3c4553bf7 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoaderData.hpp" #include "gc_implementation/g1/concurrentMarkThread.inline.hpp" #include "gc_implementation/g1/g1CollectedHeap.inline.hpp" #include "gc_implementation/g1/g1CollectorPolicy.hpp" @@ -100,6 +101,10 @@ void ConcurrentMarkThread::run() { HandleMark hm; double cycle_start = os::elapsedVTime(); + { + ClassLoaderDataGraph::clear_claimed_marks(); + } + // We have to ensure that we finish scanning the root regions // before the next GC takes place. To ensure this we have to // make sure that we do not join the STS until the root regions @@ -109,7 +114,7 @@ void ConcurrentMarkThread::run() { // correctness issue. double scan_start = os::elapsedTime(); - if (!cm()->has_aborted()) { + { if (G1Log::fine()) { gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id()); gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]"); @@ -297,6 +302,7 @@ void ConcurrentMarkThread::run() { } } assert(_should_terminate, "just checking"); + _cm->root_regions()->cancel_scan(); terminate(); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index 5b156f99d..3ff5586c1 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -1346,8 +1346,7 @@ bool G1CollectedHeap::do_collection(bool explicit_gc, ref_processor_cm()->verify_no_references_recorded(); // Abandon current iterations of concurrent marking and concurrent - // refinement, if any are in progress. We have to do this before - // wait_until_scan_finished() below. + // refinement, if any are in progress. concurrent_mark()->abort(); // Make sure we'll choose a new allocation region afterwards. @@ -4032,10 +4031,13 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { verify_region_sets_optional(); verify_dirty_young_regions(); - // This call will decide whether this pause is an initial-mark - // pause. If it is, during_initial_mark_pause() will return true - // for the duration of this pause. - g1_policy()->decide_on_conc_mark_initiation(); + // We should not be doing initial mark unless the conc mark thread is running + if (!_cmThread->should_terminate()) { + // This call will decide whether this pause is an initial-mark + // pause. If it is, during_initial_mark_pause() will return true + // for the duration of this pause. + g1_policy()->decide_on_conc_mark_initiation(); + } // We do not allow initial-mark to be piggy-backed on a mixed GC. assert(!g1_policy()->during_initial_mark_pause() || diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp index 1e16bf726..ceb65b029 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp @@ -71,6 +71,8 @@ public: // Tester bool is_ConcurrentGC_thread() const { return true; } + + bool should_terminate() { return _should_terminate; } }; // The SurrogateLockerThread is used by concurrent GC threads for -- 2.23.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2