< prev index next >

src/hotspot/share/services/threadService.cpp

Print this page
rev 47819 : imported patch 10.07.open.rebase_20171110.dcubed

@@ -32,13 +32,13 @@
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
-#include "runtime/thread.hpp"
-#include "runtime/vframe.hpp"
 #include "runtime/thread.inline.hpp"
+#include "runtime/threadSMR.inline.hpp"
+#include "runtime/vframe.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
 #include "services/threadService.hpp"
 
 // TODO: we need to define a naming convention for perf counters

@@ -146,11 +146,11 @@
 }
 
 // FIXME: JVMTI should call this function
 Handle ThreadService::get_current_contended_monitor(JavaThread* thread) {
   assert(thread != NULL, "should be non-NULL");
-  assert(Threads_lock->owned_by_self(), "must grab Threads_lock or be at safepoint");
+  debug_only(Thread::check_for_dangling_thread_pointer(thread);)
 
   ObjectMonitor *wait_obj = thread->current_waiting_monitor();
 
   oop obj = NULL;
   if (wait_obj != NULL) {

@@ -264,10 +264,11 @@
   objArrayOop r = oopFactory::new_objArray(ik, num_threads, CHECK_NH);
   objArrayHandle result_obj(THREAD, r);
 
   int num_snapshots = dump_result.num_snapshots();
   assert(num_snapshots == num_threads, "Must have num_threads thread snapshots");
+  assert(num_snapshots == 0 || dump_result.t_list_has_been_set(), "ThreadsList must have been set if we have a snapshot");
   int i = 0;
   for (ThreadSnapshot* ts = dump_result.snapshots(); ts != NULL; i++, ts = ts->next()) {
     ThreadStackTrace* stacktrace = ts->get_stack_trace();
     if (stacktrace == NULL) {
       // No stack trace

@@ -295,28 +296,31 @@
     stat->reset_time_stat();
   }
 }
 
 // Find deadlocks involving object monitors and concurrent locks if concurrent_locks is true
-DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(bool concurrent_locks) {
+DeadlockCycle* ThreadService::find_deadlocks_at_safepoint(ThreadsList * t_list, bool concurrent_locks) {
+  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
+
   // This code was modified from the original Threads::find_deadlocks code.
   int globalDfn = 0, thisDfn;
   ObjectMonitor* waitingToLockMonitor = NULL;
   oop waitingToLockBlocker = NULL;
   bool blocked_on_monitor = false;
   JavaThread *currentThread, *previousThread;
   int num_deadlocks = 0;
 
-  for (JavaThread* p = Threads::first(); p != NULL; p = p->next()) {
-    // Initialize the depth-first-number
-    p->set_depth_first_number(-1);
+  // Initialize the depth-first-number for each JavaThread.
+  JavaThreadIterator jti(t_list);
+  for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
+    jt->set_depth_first_number(-1);
   }
 
   DeadlockCycle* deadlocks = NULL;
   DeadlockCycle* last = NULL;
   DeadlockCycle* cycle = new DeadlockCycle();
-  for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {
+  for (JavaThread* jt = jti.first(); jt != NULL; jt = jti.next()) {
     if (jt->depth_first_number() >= 0) {
       // this thread was already visited
       continue;
     }
 

@@ -337,13 +341,12 @@
     while (waitingToLockMonitor != NULL || waitingToLockBlocker != NULL) {
       cycle->add_thread(currentThread);
       if (waitingToLockMonitor != NULL) {
         address currentOwner = (address)waitingToLockMonitor->owner();
         if (currentOwner != NULL) {
-          currentThread = Threads::owning_thread_from_monitor_owner(
-                            currentOwner,
-                            false /* no locking needed */);
+          currentThread = Threads::owning_thread_from_monitor_owner(t_list,
+                                                                    currentOwner);
           if (currentThread == NULL) {
             // This function is called at a safepoint so the JavaThread
             // that owns waitingToLockMonitor should be findable, but
             // if it is not findable, then the previous currentThread is
             // blocked permanently. We record this as a deadlock.

@@ -364,10 +367,12 @@
         }
       } else {
         if (concurrent_locks) {
           if (waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass())) {
             oop threadObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker);
+            // This JavaThread (if there is one) is protected by the
+            // ThreadsListSetter in VM_FindDeadlocks::doit().
             currentThread = threadObj != NULL ? java_lang_Thread::thread(threadObj) : NULL;
           } else {
             currentThread = NULL;
           }
         }

@@ -412,19 +417,19 @@
   }
   delete cycle;
   return deadlocks;
 }
 
-ThreadDumpResult::ThreadDumpResult() : _num_threads(0), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL) {
+ThreadDumpResult::ThreadDumpResult() : _num_threads(0), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL), _setter() {
 
   // Create a new ThreadDumpResult object and append to the list.
   // If GC happens before this function returns, Method*
   // in the stack trace will be visited.
   ThreadService::add_thread_dump(this);
 }
 
-ThreadDumpResult::ThreadDumpResult(int num_threads) : _num_threads(num_threads), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL) {
+ThreadDumpResult::ThreadDumpResult(int num_threads) : _num_threads(num_threads), _num_snapshots(0), _snapshots(NULL), _next(NULL), _last(NULL), _setter() {
   // Create a new ThreadDumpResult object and append to the list.
   // If GC happens before this function returns, oops
   // will be visited.
   ThreadService::add_thread_dump(this);
 }

@@ -465,10 +470,14 @@
   for (ThreadSnapshot* ts = _snapshots; ts != NULL; ts = ts->next()) {
     ts->metadata_do(f);
   }
 }
 
+ThreadsList* ThreadDumpResult::t_list() {
+  return _setter.list();
+}
+
 StackFrameInfo::StackFrameInfo(javaVFrame* jvf, bool with_lock_info) {
   _method = jvf->method();
   _bci = jvf->bci();
   _class_holder = _method->method_holder()->klass_holder();
   _locked_monitors = NULL;

@@ -681,10 +690,12 @@
   int length = aos_objects->length();
   for (int i = 0; i < length; i++) {
     oop o = aos_objects->at(i);
     oop owner_thread_obj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(o);
     if (owner_thread_obj != NULL) {
+      // See comments in ThreadConcurrentLocks to see how this
+      // JavaThread* is protected.
       JavaThread* thread = java_lang_Thread::thread(owner_thread_obj);
       assert(o->is_instance(), "Must be an instanceOop");
       add_lock(thread, (instanceOop) o);
     }
   }

@@ -762,11 +773,11 @@
   _count_pending_reset = false;
   _timer_pending_reset = false;
   memset((void*) _perf_recursion_counts, 0, sizeof(_perf_recursion_counts));
 }
 
-ThreadSnapshot::ThreadSnapshot(JavaThread* thread) {
+ThreadSnapshot::ThreadSnapshot(ThreadsList * t_list, JavaThread* thread) {
   _thread = thread;
   _threadObj = thread->threadObj();
   _stack_trace = NULL;
   _concurrent_locks = NULL;
   _next = NULL;

@@ -794,11 +805,11 @@
     if (obj() == NULL) {
       // monitor no longer exists; thread is not blocked
       _thread_status = java_lang_Thread::RUNNABLE;
     } else {
       _blocker_object = obj();
-      JavaThread* owner = ObjectSynchronizer::get_lock_owner(obj, false);
+      JavaThread* owner = ObjectSynchronizer::get_lock_owner(t_list, obj);
       if ((owner == NULL && _thread_status == java_lang_Thread::BLOCKED_ON_MONITOR_ENTER)
           || (owner != NULL && owner->is_attaching_via_jni())) {
         // ownership information of the monitor is not available
         // (may no longer be owned or releasing to some other thread)
         // make this thread in RUNNABLE state.

@@ -863,11 +874,11 @@
 
 DeadlockCycle::~DeadlockCycle() {
   delete _threads;
 }
 
-void DeadlockCycle::print_on(outputStream* st) const {
+void DeadlockCycle::print_on_with(ThreadsList * t_list, outputStream* st) const {
   st->cr();
   st->print_cr("Found one Java-level deadlock:");
   st->print("=============================");
 
   JavaThread* currentThread;

@@ -893,13 +904,12 @@
         }
       } else {
         // No Java object associated - a JVMTI raw monitor
         owner_desc = " (JVMTI raw monitor),\n  which is held by";
       }
-      currentThread = Threads::owning_thread_from_monitor_owner(
-                        (address)waitingToLockMonitor->owner(),
-                        false /* no locking needed */);
+      currentThread = Threads::owning_thread_from_monitor_owner(t_list,
+                                                                (address)waitingToLockMonitor->owner());
       if (currentThread == NULL) {
         // The deadlock was detected at a safepoint so the JavaThread
         // that owns waitingToLockMonitor should be findable, but
         // if it is not findable, then the previous currentThread is
         // blocked permanently.

@@ -913,10 +923,11 @@
                 waitingToLockBlocker->klass()->external_name());
       assert(waitingToLockBlocker->is_a(SystemDictionary::abstract_ownable_synchronizer_klass()),
              "Must be an AbstractOwnableSynchronizer");
       oop ownerObj = java_util_concurrent_locks_AbstractOwnableSynchronizer::get_owner_threadObj(waitingToLockBlocker);
       currentThread = java_lang_Thread::thread(ownerObj);
+      assert(currentThread != NULL, "AbstractOwnableSynchronizer owning thread is unexpectedly NULL");
     }
     st->print("%s \"%s\"", owner_desc, currentThread->get_thread_name());
   }
 
   st->cr();

@@ -941,13 +952,11 @@
   assert(cur_thread == Thread::current(), "Check current thread");
 
   int init_size = ThreadService::get_live_thread_count();
   _threads_array = new GrowableArray<instanceHandle>(init_size);
 
-  MutexLockerEx ml(Threads_lock);
-
-  for (JavaThread* jt = Threads::first(); jt != NULL; jt = jt->next()) {
+  for (JavaThreadIteratorWithHandle jtiwh; JavaThread *jt = jtiwh.next(); ) {
     // skips JavaThreads in the process of exiting
     // and also skips VM internal JavaThreads
     // Threads in _thread_new or _thread_new_trans state are included.
     // i.e. threads have been started but not yet running.
     if (jt->threadObj() == NULL   ||
< prev index next >