JDK-8200374 : Add ThreadsSMRSupport::verify_hazard_pointer_scanned() to verify threads_do()
  • Type: Enhancement
  • Component: hotspot
  • Sub-Component: runtime
  • Affected Version: 11
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2018-03-28
  • Updated: 2019-06-20
  • Resolved: 2018-04-12
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 11
11 b10Fixed
Related Reports
Relates :  
Description
During the code review cycle for JDK-8199813, Erik O
came up with a way to verify the contract for thread_do()
which is currently only in comment form:

// All JavaThreads + all non-JavaThreads (i.e., every thread in the system)
void Threads::threads_do(ThreadClosure* tc) {

This new function will be called:

ThreadsSMRSupport::verify_hazard_pointer_scanned()

and will require some support infrastructure changes
to implement it.
Comments
I temporarily restored the failing code in JavaThread::verify_not_published() to test the new function. Here's the diffs (plus a couple of improvements): $ hg diff diff -r df946ef9863e src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp Wed Mar 28 20:16:43 2018 -0400 +++ b/src/hotspot/share/runtime/thread.cpp Thu Mar 29 11:23:06 2018 -0400 @@ -2396,11 +2396,16 @@ // Verify the JavaThread has not yet been published in the Threads::list, and // hence doesn't need protection from concurrent access at this stage. void JavaThread::verify_not_published() { +if (UseNewCode) { + ThreadsListHandle tlh; + assert(!tlh.includes(this), "JavaThread shouldn't have been published yet!"); +} else { // Cannot create a ThreadsListHandle here and check !tlh.includes(this) // since an unpublished JavaThread doesn't participate in the // Thread-SMR protocol for keeping a ThreadsList alive. assert(!on_thread_list(), "JavaThread shouldn't have been published yet!"); } +} #endif // Slow path when the native==>VM/Java barriers detect a safepoint is in @@ -3438,7 +3443,9 @@ // Someday we could have a table or list of all non-JavaThreads. // For now, just manually iterate through them. tc->do_thread(VMThread::vm_thread()); - Universe::heap()->gc_threads_do(tc); + if (Universe::heap() != NULL) { + Universe::heap()->gc_threads_do(tc); + } WatcherThread *wt = WatcherThread::watcher_thread(); // Strictly speaking, the following NULL check isn't sufficient to make sure // the data for WatcherThread is still valid upon being examined. However, diff -r df946ef9863e src/hotspot/share/runtime/threadSMR.cpp --- a/src/hotspot/share/runtime/threadSMR.cpp Wed Mar 28 20:16:43 2018 -0400 +++ b/src/hotspot/share/runtime/threadSMR.cpp Thu Mar 29 11:23:06 2018 -0400 @@ -580,6 +580,8 @@ // the Thread-SMR protocol. void ThreadsSMRSupport::verify_hazard_pointer_scanned(Thread *self, ThreadsList *threads) { #ifdef ASSERT + assert(threads != NULL, "threads must not be NULL"); + // The closure will attempt to verify that the calling thread can // be found by threads_do() on the specified ThreadsList. If it // is successful, then the specified ThreadsList was acquired as With the '-XX:+UseNewCode' option added, here's what the jni008 failure looks like: # Internal Error (/work/shared/bug_hunt/8200374/8200374_for_jdk_hs/open/src/hotspot/share/runtime/threadSMR.cpp:612), pid=75153, tid=1811 # assert(cl.found() || self == VM_Exit::shutdown_thread()) failed: Acquired a ThreadsList snapshot from a thread not recognized by the Thread-SMR protocol. See the attached doit.jni008.slowdebug.hs_err_pid.fails_assert and doit.jni008.slowdebug.log.fails_assert logs for the gory details.
29-03-2018