JDK-8273300 : Check Mutex ranking during a safepoint
  • Type: Sub-task
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 18
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2021-09-02
  • Updated: 2021-09-20
  • Resolved: 2021-09-16
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 18
18 masterFixed
Description
The Mutex rank checking is excluded during a safepoint likely for historical reasons when the Threads_lock or Safepoint_lock were held.  It's better to not have this condition while rank checking, but removing it requires reassigning some Mutex ranks:

    owns -> takes (so reduce rank)

    SystemDictionary_lock(leaf) -> DumpTimeTable_lock(leaf-1) -> Zip_lock(leaf-2)
                                                                                                     -> Uncommit_lock(leaf-2)
                                                                                                     -> ConcurrentHashTableResize_lock(leaf-2)
                                                                                                     -> VtableStubs_lock(leaf-2)
                                                                                                     -> MetaspaceAllocation_lock(leaf -2)      
                                                                                                                         ->Metaspace_lock(leaf-3)

    CGC_lock(leaf) -> RootRegionScan_lock(leaf-1)
                             -> NonJavaThreadsListLock(leaf-1) -> G1DetachedRefinementStats_lock(leaf-2)

    FreeList_lock(leaf) -> Uncommit_lock(leaf-2)                       -> G1Mapper_lock(leaf-3)
                                       -> HeapRegionParAlloc_lock(leaf-1)


If the Service_lock is only taken if  not at_safepoint for oops_do/nmethods_do functions so we don't have to reduce the ranks of the G1 threads because of G1 locks taken at a safepoint.  The code adding to the ServiceThread's jvmti deferred event queue are either at a safepoint for G1 or not for concurrent GCs.

     Service_lock(service) -> HeapRegionRemSet#n_lock(service-1)
                                            -> FreeList_lock(should be service -1 now)

    StackWaterMark_lock(stackwatermark) -> Service_lock(service) for ServiceThread::oops_do_no_frames.

Comments
Changeset: 5e4d09c2 Author: Coleen Phillimore <coleenp@openjdk.org> Date: 2021-09-16 12:01:49 +0000 URL: https://git.openjdk.java.net/jdk/commit/5e4d09c22921f2980f84f849eb600d2e524d0733
16-09-2021

_par_alloc_lock(Mutex::service-2, "HeapRegionParAlloc_lock", Mutex::_safepoint_check_never), This patch changes this lock to safepoint_check_never because it's taken out holding a safepoint_check_never lock (FreeList_lock). It should assert that it can't block but it doesn't because the assert is only for JavaThreads, and it's not taken out by a JavaThread when holding FreeList_lock apparently, if it's taken by a JavaThread at all.
09-09-2021

[~eosterlund]: "What scares me is when the lock ranking system introduces bugs instead of preventing them, by making it tempting to use looser synchronization or hard to reason about synchronization, because actually updating the ranks manually is too tedious." Changing how the service thread handles deferred events fits into this description. The events are processed by the service thread, iterated upon by the GC threads with and without safepoints, but can be added by any other thread, also with and without safepoints. Having a lock, like Service_lock protect this static queue is the simplest and most reliable code.
08-09-2021