--- old/src/hotspot/share/runtime/thread.cpp Tue Nov 21 15:20:37 2017 +++ new/src/hotspot/share/runtime/thread.cpp Tue Nov 21 15:20:36 2017 @@ -3429,10 +3429,15 @@ // ======= 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; @@ -3440,6 +3445,7 @@ 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 */, @@ -3446,22 +3452,86 @@ 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 @@ -4826,8 +4896,8 @@ // 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(); } @@ -4834,7 +4904,7 @@ 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); @@ -5419,8 +5489,8 @@ 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, @@ -5428,19 +5498,19 @@ _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);