< prev index next >

src/hotspot/share/runtime/thread.cpp

Print this page
rev 47862 : imported patch 10.07.open.rebase_20171110.dcubed
rev 47863 : imported patch 10.08.open.rebase_20171114.rehn
rev 47864 : imported patch 10.09.open.TLH_hang_fix.rehn
rev 47865 : dholmes CR: Fix indents, trailing spaces and various typos. Add descriptions for the '_cnt', '_max' and '_times" fields, add impl notes to document the type choices.
rev 47866 : robinw CR: Fix some inefficient code, update some comments, fix some indents, and add some 'const' specifiers.

@@ -3427,43 +3427,113 @@
 
 
 // ======= Threads ========
 
 // The Threads class links together all active threads, and provides
-// operations over all threads.  It is protected by its own Mutex
-// lock, which is also used in other contexts to protect thread
-// operations from having the thread being operated on from exiting
-// and going away unexpectedly (e.g., safepoint synchronization)
+// operations over all threads. It is protected by the Threads_lock,
+// which is also used in other global contexts like safepointing.
+// ThreadsListHandles are used to safely perform operations on one
+// or more threads without the risk of the thread exiting during the
+// operation.
+//
+// Note: The Threads_lock is currently more widely used than we
+// would like. We are actively migrating Threads_lock uses to other
+// mechanisms in order to reduce Threads_lock contention.
 
 JavaThread*           Threads::_thread_list = NULL;
 int                   Threads::_number_of_threads = 0;
 int                   Threads::_number_of_non_daemon_threads = 0;
 int                   Threads::_return_code = 0;
 int                   Threads::_thread_claim_parity = 0;
 size_t                JavaThread::_stack_size_at_create = 0;
+// Safe Memory Reclamation (SMR) support:
 Monitor*              Threads::_smr_delete_lock =
                           new Monitor(Monitor::special, "smr_delete_lock",
                                       false /* allow_vm_block */,
                                       Monitor::_safepoint_check_never);
 // The '_cnt', '_max' and '_times" fields are enabled via
 // -XX:+EnableThreadSMRStatistics:
+
+// # of parallel threads in _smr_delete_lock->wait().
+// Impl note: Hard to imagine > 64K waiting threads so this could be 16-bit,
+// but there is no nice 16-bit _FORMAT support.
 uint                  Threads::_smr_delete_lock_wait_cnt = 0;
+
+// Max # of parallel threads in _smr_delete_lock->wait().
+// Impl note: See _smr_delete_lock_wait_cnt note.
 uint                  Threads::_smr_delete_lock_wait_max = 0;
-volatile jint         Threads::_smr_delete_notify = 0;
-volatile jint         Threads::_smr_deleted_thread_cnt = 0;
-volatile jint         Threads::_smr_deleted_thread_time_max = 0;
-volatile jint         Threads::_smr_deleted_thread_times = 0;
+
+// Flag to indicate when an _smr_delete_lock->notify() is needed.
+// Impl note: See _smr_delete_lock_wait_cnt note.
+volatile uint         Threads::_smr_delete_notify = 0;
+
+// # of threads deleted over VM lifetime.
+// Impl note: Atomically incremented over VM lifetime so use unsigned for more
+// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc
+// isn't available everywhere (or is it?).
+volatile uint         Threads::_smr_deleted_thread_cnt = 0;
+
+// Max time in millis to delete a thread.
+// Impl note: 16-bit might be too small on an overloaded machine. Use
+// unsigned since this is a time value. Set via Atomic::cmpxchg() in a
+// loop for correctness.
+volatile uint         Threads::_smr_deleted_thread_time_max = 0;
+
+// Cumulative time in millis to delete threads.
+// Impl note: Atomically added to over VM lifetime so use unsigned for more
+// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc
+// isn't available everywhere (or is it?).
+volatile uint         Threads::_smr_deleted_thread_times = 0;
+
 ThreadsList* volatile Threads::_smr_java_thread_list = new ThreadsList(0);
-long                  Threads::_smr_java_thread_list_alloc_cnt = 1;
-long                  Threads::_smr_java_thread_list_free_cnt = 0;
+
+// # of ThreadsLists allocated over VM lifetime.
+// Impl note: We allocate a new ThreadsList for every thread create and
+// every thread delete so we need a bigger type than the
+// _smr_deleted_thread_cnt field.
+uint64_t              Threads::_smr_java_thread_list_alloc_cnt = 1;
+
+// # of ThreadsLists freed over VM lifetime.
+// Impl note: See _smr_java_thread_list_alloc_cnt note.
+uint64_t              Threads::_smr_java_thread_list_free_cnt = 0;
+
+// Max size ThreadsList allocated.
+// Impl note: Max # of threads alive at one time should fit in unsigned 32-bit.
 uint                  Threads::_smr_java_thread_list_max = 0;
+
+// Max # of nested ThreadsLists for a thread.
+// Impl note: Hard to imagine > 64K nested ThreadsLists so this could be
+// 16-bit, but there is no nice 16-bit _FORMAT support.
 uint                  Threads::_smr_nested_thread_list_max = 0;
-volatile jint         Threads::_smr_tlh_cnt = 0;
-volatile jint         Threads::_smr_tlh_time_max = 0;
-volatile jint         Threads::_smr_tlh_times = 0;
+
+// # of ThreadsListHandles deleted over VM lifetime.
+// Impl note: Atomically incremented over VM lifetime so use unsigned for
+// more range. There will be fewer ThreadsListHandles than threads so
+// unsigned 32-bit should be fine.
+volatile uint         Threads::_smr_tlh_cnt = 0;
+
+// Max time in millis to delete a ThreadsListHandle.
+// Impl note: 16-bit might be too small on an overloaded machine. Use
+// unsigned since this is a time value. Set via Atomic::cmpxchg() in a
+// loop for correctness.
+volatile uint         Threads::_smr_tlh_time_max = 0;
+
+// Cumulative time in millis to delete ThreadsListHandles.
+// Impl note: Atomically added to over VM lifetime so use unsigned for more
+// range. Unsigned 64-bit would be more future proof, but 64-bit atomic inc
+// isn't available everywhere (or is it?).
+volatile uint         Threads::_smr_tlh_times = 0;
+
 ThreadsList*          Threads::_smr_to_delete_list = NULL;
+
+// # of parallel ThreadsLists on the to-delete list.
+// Impl note: Hard to imagine > 64K ThreadsLists needing to be deleted so
+// this could be 16-bit, but there is no nice 16-bit _FORMAT support.
 uint                  Threads::_smr_to_delete_list_cnt = 0;
+
+// Max # of parallel ThreadsLists on the to-delete list.
+// Impl note: See _smr_to_delete_list_cnt note.
 uint                  Threads::_smr_to_delete_list_max = 0;
 
 #ifdef ASSERT
 bool                  Threads::_vm_complete = false;
 #endif

@@ -4824,19 +4894,19 @@
     Threads::clear_smr_delete_notify();
     Threads::smr_delete_lock()->unlock();
     // Retry the whole scenario.
   }
 
-  // If someone set a handshake on us just as we entered exit path, we simple cancel it.
   if (ThreadLocalHandshakes) {
+    // The thread is about to be deleted so cancel any handshake.
     thread->cancel_handshake();
   }
 
   delete thread;
   if (EnableThreadSMRStatistics) {
     timer.stop();
-    jint millis = (jint)timer.milliseconds();
+    uint millis = (uint)timer.milliseconds();
     Threads::inc_smr_deleted_thread_cnt();
     Threads::add_smr_deleted_thread_times(millis);
     Threads::update_smr_deleted_thread_time_max(millis);
   }
 

@@ -5417,32 +5487,32 @@
     }
   }
   if (!EnableThreadSMRStatistics) {
     return;
   }
-  st->print_cr("_smr_java_thread_list_alloc_cnt=%ld, "
-               "_smr_java_thread_list_free_cnt=%ld, "
+  st->print_cr("_smr_java_thread_list_alloc_cnt=" UINT64_FORMAT ","
+               "_smr_java_thread_list_free_cnt=" UINT64_FORMAT ","
                "_smr_java_thread_list_max=%u, "
                "_smr_nested_thread_list_max=%u",
                _smr_java_thread_list_alloc_cnt,
                _smr_java_thread_list_free_cnt,
                _smr_java_thread_list_max,
                _smr_nested_thread_list_max);
   if (_smr_tlh_cnt > 0) {
-    st->print_cr("_smr_tlh_cnt=" INT32_FORMAT
-                 ", _smr_tlh_times=" INT32_FORMAT
+    st->print_cr("_smr_tlh_cnt=%u"
+                 ", _smr_tlh_times=%u"
                  ", avg_smr_tlh_time=%0.2f"
-                 ", _smr_tlh_time_max=" INT32_FORMAT,
+                 ", _smr_tlh_time_max=%u",
                  _smr_tlh_cnt, _smr_tlh_times,
                  ((double) _smr_tlh_times / _smr_tlh_cnt),
                  _smr_tlh_time_max);
   }
   if (_smr_deleted_thread_cnt > 0) {
-    st->print_cr("_smr_deleted_thread_cnt=" INT32_FORMAT
-                 ", _smr_deleted_thread_times=" INT32_FORMAT
+    st->print_cr("_smr_deleted_thread_cnt=%u"
+                 ", _smr_deleted_thread_times=%u"
                  ", avg_smr_deleted_thread_time=%0.2f"
-                 ", _smr_deleted_thread_time_max=" INT32_FORMAT,
+                 ", _smr_deleted_thread_time_max=%u",
                  _smr_deleted_thread_cnt, _smr_deleted_thread_times,
                  ((double) _smr_deleted_thread_times / _smr_deleted_thread_cnt),
                  _smr_deleted_thread_time_max);
   }
   st->print_cr("_smr_delete_lock_wait_cnt=%u, _smr_delete_lock_wait_max=%u",
< prev index next >