8226228: Make Threads_lock an always safepoint checked lock.
authorrehn
Fri, 09 Aug 2019 11:04:08 +0200
changeset 57699 4aea554692aa
parent 57698 9dc92e89243a
child 57700 def8e77a3ad1
8226228: Make Threads_lock an always safepoint checked lock. Reviewed-by: coleenp, dcubed, dholmes
src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp
src/hotspot/share/prims/jni.cpp
src/hotspot/share/runtime/handshake.cpp
src/hotspot/share/runtime/mutex.cpp
src/hotspot/share/runtime/mutexLocker.cpp
src/hotspot/share/runtime/thread.cpp
src/hotspot/share/runtime/thread.hpp
src/hotspot/share/runtime/threadSMR.cpp
src/hotspot/share/runtime/vmOperations.cpp
src/hotspot/share/utilities/vmError.cpp
--- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -516,7 +516,7 @@
     elapsedTimer sample_time;
     sample_time.start();
     {
-      MutexLocker tlock(Threads_lock, Mutex::_no_safepoint_check_flag);
+      MutexLocker tlock(Threads_lock);
       ThreadsListHandle tlh;
       // Resolve a sample session relative start position index into the thread list array.
       // In cases where the last sampled thread is NULL or not-NULL but stale, find_index() returns -1.
--- a/src/hotspot/share/prims/jni.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/prims/jni.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -4135,14 +4135,13 @@
 
   thread->cache_global_variables();
 
-  // Crucial that we do not have a safepoint check for this thread, since it has
+  // This thread will not do a safepoint check, since it has
   // not been added to the Thread list yet.
-  { Threads_lock->lock_without_safepoint_check();
+  { MutexLocker ml(Threads_lock);
     // This must be inside this lock in order to get FullGCALot to work properly, i.e., to
     // avoid this thread trying to do a GC before it is added to the thread-list
     thread->set_active_handles(JNIHandleBlock::allocate_block());
     Threads::add(thread, daemon);
-    Threads_lock->unlock();
   }
   // Create thread group and name info from attach arguments
   oop group = NULL;
--- a/src/hotspot/share/runtime/handshake.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/runtime/handshake.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -137,7 +137,7 @@
       // There is an assumption in the code that the Threads_lock should be
       // locked during certain phases.
       {
-        MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+        MutexLocker ml(Threads_lock);
         _target->handshake_process_by_vmthread();
       }
     } while (!poll_for_completed_thread());
@@ -186,7 +186,7 @@
           // There is an assumption in the code that the Threads_lock should
           // be locked during certain phases.
           jtiwh.rewind();
-          MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+          MutexLocker ml(Threads_lock);
           for (JavaThread *thr = jtiwh.next(); thr != NULL; thr = jtiwh.next()) {
             // A new thread on the ThreadsList will not have an operation,
             // hence it is skipped in handshake_process_by_vmthread.
--- a/src/hotspot/share/runtime/mutex.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/runtime/mutex.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -37,7 +37,7 @@
   // If the JavaThread checks for safepoint, verify that the lock wasn't created with safepoint_check_never.
   SafepointCheckRequired not_allowed = do_safepoint_check ?  Monitor::_safepoint_check_never :
                                                              Monitor::_safepoint_check_always;
-  assert(!thread->is_Java_thread() || _safepoint_check_required != not_allowed,
+  assert(!thread->is_active_Java_thread() || _safepoint_check_required != not_allowed,
          "This lock should %s have a safepoint check for Java threads: %s",
          _safepoint_check_required ? "always" : "never", name());
 
@@ -52,7 +52,7 @@
 
 #ifdef CHECK_UNHANDLED_OOPS
   // Clear unhandled oops in JavaThreads so we get a crash right away.
-  if (self->is_Java_thread()) {
+  if (self->is_active_Java_thread()) {
     self->clear_unhandled_oops();
   }
 #endif // CHECK_UNHANDLED_OOPS
@@ -62,6 +62,7 @@
 
   Monitor* in_flight_monitor = NULL;
   DEBUG_ONLY(int retry_cnt = 0;)
+  bool is_active_Java_thread = self->is_active_Java_thread();
   while (!_lock.try_lock()) {
     // The lock is contended
 
@@ -72,7 +73,8 @@
     }
   #endif // ASSERT
 
-    if (self->is_Java_thread()) {
+    // Is it a JavaThread participating in the safepoint protocol.
+    if (is_active_Java_thread) {
       assert(rank() > Mutex::special, "Potential deadlock with special or lesser rank mutex");
       { ThreadBlockInVMWithDeadlockCheck tbivmdc((JavaThread *) self, &in_flight_monitor);
         in_flight_monitor = this;  // save for ~ThreadBlockInVMWithDeadlockCheck
@@ -190,8 +192,8 @@
 
   assert_owner(self);
 
-  // Safepoint checking logically implies java_thread
-  guarantee(self->is_Java_thread(), "invariant");
+  // Safepoint checking logically implies an active JavaThread.
+  guarantee(self->is_active_Java_thread(), "invariant");
   assert_wait_lock_state(self);
 
 #ifdef CHECK_UNHANDLED_OOPS
@@ -470,7 +472,7 @@
 // Factored out common sanity checks for locking mutex'es. Used by lock() and try_lock()
 void Monitor::check_prelock_state(Thread *thread, bool safepoint_check) {
   if (safepoint_check) {
-    assert((!thread->is_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm)
+    assert((!thread->is_active_Java_thread() || ((JavaThread *)thread)->thread_state() == _thread_in_vm)
            || rank() == Mutex::special, "wrong thread state for using locks");
     if (thread->is_VM_thread() && !allow_vm_block()) {
       fatal("VM thread using lock %s (not allowed to block on)", name());
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -287,7 +287,7 @@
   // CMS_bitMap_lock                          leaf 1
   // CMS_freeList_lock                        leaf 2
 
-  def(Threads_lock                 , PaddedMonitor, barrier,     true,  Monitor::_safepoint_check_sometimes);  // Used for safepoint protocol.
+  def(Threads_lock                 , PaddedMonitor, barrier,     true,  Monitor::_safepoint_check_always);  // Used for safepoint protocol.
   def(NonJavaThreadsList_lock      , PaddedMutex,   leaf,        true,  Monitor::_safepoint_check_never);
   def(NonJavaThreadsListSync_lock  , PaddedMutex,   leaf,        true,  Monitor::_safepoint_check_never);
 
--- a/src/hotspot/share/runtime/thread.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/runtime/thread.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -1804,7 +1804,7 @@
   if (_terminated == _vm_exited) {
     // _vm_exited is set at safepoint, and Threads_lock is never released
     // we will block here forever
-    Threads_lock->lock_without_safepoint_check();
+    Threads_lock->lock();
     ShouldNotReachHere();
   }
 }
--- a/src/hotspot/share/runtime/thread.hpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/runtime/thread.hpp	Fri Aug 09 11:04:08 2019 +0200
@@ -491,6 +491,10 @@
   // Can this thread make Java upcalls
   virtual bool can_call_java() const                 { return false; }
 
+  // Is this a JavaThread that is on the VM's current ThreadsList?
+  // If so it must participate in the safepoint protocol.
+  virtual bool is_active_Java_thread() const         { return false; }
+
   // Casts
   virtual WorkerThread* as_Worker_thread() const     { return NULL; }
 
@@ -1247,6 +1251,10 @@
   virtual bool is_Java_thread() const            { return true;  }
   virtual bool can_call_java() const             { return true; }
 
+  virtual bool is_active_Java_thread() const {
+    return on_thread_list() && !is_terminated();
+  }
+
   // Thread oop. threadObj() can be NULL for initial JavaThread
   // (or for threads attached via JNI)
   oop threadObj() const                          { return _threadObj; }
--- a/src/hotspot/share/runtime/threadSMR.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/runtime/threadSMR.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -942,9 +942,9 @@
 
   while (true) {
     {
-      // No safepoint check because this JavaThread is not on the
-      // Threads list.
-      MutexLocker ml(Threads_lock, Mutex::_no_safepoint_check_flag);
+      // Will not make a safepoint check because this JavaThread
+      // is not on the current ThreadsList.
+      MutexLocker ml(Threads_lock);
       // Cannot use a MonitorLocker helper here because we have
       // to drop the Threads_lock first if we wait.
       ThreadsSMRSupport::delete_lock()->lock_without_safepoint_check();
--- a/src/hotspot/share/runtime/vmOperations.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/runtime/vmOperations.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -522,7 +522,7 @@
       Thread::current_or_null() != _shutdown_thread) {
     // _vm_exited is set at safepoint, and the Threads_lock is never released
     // we will block here until the process dies
-    Threads_lock->lock_without_safepoint_check();
+    Threads_lock->lock();
     ShouldNotReachHere();
   }
 }
--- a/src/hotspot/share/utilities/vmError.cpp	Fri Aug 09 10:06:44 2019 +0200
+++ b/src/hotspot/share/utilities/vmError.cpp	Fri Aug 09 11:04:08 2019 +0200
@@ -1797,11 +1797,14 @@
   // Case 16 is tested by test/hotspot/jtreg/runtime/ErrorHandling/ThreadsListHandleInErrorHandlingTest.java.
   // Case 17 is tested by test/hotspot/jtreg/runtime/ErrorHandling/NestedThreadsListHandleInErrorHandlingTest.java.
 
-  // We grab Threads_lock to keep ThreadsSMRSupport::print_info_on()
+  // We try to grab Threads_lock to keep ThreadsSMRSupport::print_info_on()
   // from racing with Threads::add() or Threads::remove() as we
   // generate the hs_err_pid file. This makes our ErrorHandling tests
   // more stable.
-  MutexLocker ml(Threads_lock->owned_by_self() ? NULL : Threads_lock, Mutex::_no_safepoint_check_flag);
+  if (!Threads_lock->owned_by_self()) {
+    Threads_lock->try_lock();
+    // The VM is going to die so no need to unlock Thread_lock.
+  }
 
   switch (how) {
     case  1: vmassert(str == NULL, "expected null"); break;