8209976: Improve iteration over non-JavaThreads

Add NonJavaThread and move NamedThread iteration to new class.

Reviewed-by: eosterlund, coleenp, rkennke
This commit is contained in:
Kim Barrett 2018-08-28 16:04:54 -04:00
parent 1ddabdf0dc
commit e1059f1301
8 changed files with 107 additions and 121 deletions

View file

@ -86,6 +86,7 @@
#include "runtime/prefetch.inline.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/safepointMechanism.inline.hpp"
#include "runtime/safepointVerifiers.hpp"
#include "runtime/sharedRuntime.hpp"
#include "runtime/statSampler.hpp"
#include "runtime/stubRoutines.hpp"
@ -168,13 +169,6 @@ void universe_post_module_init(); // must happen after call_initPhase2
// Current thread is maintained as a thread-local variable
THREAD_LOCAL_DECL Thread* Thread::_thr_current = NULL;
#endif
// Class hierarchy
// - Thread
// - VMThread
// - WatcherThread
// - ConcurrentMarkSweepThread
// - JavaThread
// - CompilerThread
// ======= Thread ========
// Support for forcing alignment of thread objects for biased locking
@ -1207,61 +1201,63 @@ void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name
THREAD);
}
// List of all NamedThreads and safe iteration over that list.
// List of all NonJavaThreads and safe iteration over that list.
class NamedThread::List {
class NonJavaThread::List {
public:
NamedThread* volatile _head;
NonJavaThread* volatile _head;
SingleWriterSynchronizer _protect;
List() : _head(NULL), _protect() {}
};
NamedThread::List NamedThread::_the_list;
NonJavaThread::List NonJavaThread::_the_list;
NamedThread::Iterator::Iterator() :
NonJavaThread::Iterator::Iterator() :
_protect_enter(_the_list._protect.enter()),
_current(OrderAccess::load_acquire(&_the_list._head))
{}
NamedThread::Iterator::~Iterator() {
NonJavaThread::Iterator::~Iterator() {
_the_list._protect.exit(_protect_enter);
}
void NamedThread::Iterator::step() {
void NonJavaThread::Iterator::step() {
assert(!end(), "precondition");
_current = OrderAccess::load_acquire(&_current->_next_named_thread);
_current = OrderAccess::load_acquire(&_current->_next);
}
NonJavaThread::NonJavaThread() : Thread(), _next(NULL) {
// Add this thread to _the_list.
MutexLockerEx lock(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
_next = _the_list._head;
OrderAccess::release_store(&_the_list._head, this);
}
NonJavaThread::~NonJavaThread() {
// Remove this thread from _the_list.
MutexLockerEx lock(NonJavaThreadsList_lock, Mutex::_no_safepoint_check_flag);
NonJavaThread* volatile* p = &_the_list._head;
for (NonJavaThread* t = *p; t != NULL; p = &t->_next, t = *p) {
if (t == this) {
*p = this->_next;
// Wait for any in-progress iterators.
_the_list._protect.synchronize();
break;
}
}
}
// NamedThread -- non-JavaThread subclasses with multiple
// uniquely named instances should derive from this.
NamedThread::NamedThread() :
Thread(),
NonJavaThread(),
_name(NULL),
_processed_thread(NULL),
_gc_id(GCId::undefined()),
_next_named_thread(NULL)
{
// Add this thread to _the_list.
MutexLockerEx lock(NamedThreadsList_lock, Mutex::_no_safepoint_check_flag);
_next_named_thread = _the_list._head;
OrderAccess::release_store(&_the_list._head, this);
}
_gc_id(GCId::undefined())
{}
NamedThread::~NamedThread() {
// Remove this thread from _the_list.
{
MutexLockerEx lock(NamedThreadsList_lock, Mutex::_no_safepoint_check_flag);
NamedThread* volatile* p = &_the_list._head;
for (NamedThread* t = *p; t != NULL; p = &t->_next_named_thread, t = *p) {
if (t == this) {
*p = this->_next_named_thread;
// Wait for any in-progress iterators.
_the_list._protect.synchronize();
break;
}
}
}
if (_name != NULL) {
FREE_C_HEAP_ARRAY(char, _name);
_name = NULL;
@ -1299,7 +1295,7 @@ WatcherThread* WatcherThread::_watcher_thread = NULL;
bool WatcherThread::_startable = false;
volatile bool WatcherThread::_should_terminate = false;
WatcherThread::WatcherThread() : Thread() {
WatcherThread::WatcherThread() : NonJavaThread() {
assert(watcher_thread() == NULL, "we can only allocate one WatcherThread");
if (os::create_thread(this, os::watcher_thread)) {
_watcher_thread = this;
@ -3430,35 +3426,12 @@ static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) {
// All JavaThreads
#define ALL_JAVA_THREADS(X) DO_JAVA_THREADS(ThreadsSMRSupport::get_java_thread_list(), X)
// All non-JavaThreads (i.e., every non-JavaThread in the system).
// All NonJavaThreads (i.e., every non-JavaThread in the system).
void Threads::non_java_threads_do(ThreadClosure* tc) {
// 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());
if (Universe::heap() != NULL) {
Universe::heap()->gc_threads_do(tc);
NoSafepointVerifier nsv(!SafepointSynchronize::is_at_safepoint(), false);
for (NonJavaThread::Iterator njti; !njti.end(); njti.step()) {
tc->do_thread(njti.current());
}
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,
// considering that WatchThread terminates when the VM is on the way to
// exit at safepoint, the chance of the above is extremely small. The right
// way to prevent termination of WatcherThread would be to acquire
// Terminator_lock, but we can't do that without violating the lock rank
// checking in some cases.
if (wt != NULL) {
tc->do_thread(wt);
}
#if INCLUDE_JFR
Thread* sampler_thread = Jfr::sampler_thread();
if (sampler_thread != NULL) {
tc->do_thread(sampler_thread);
}
#endif
// If CompilerThreads ever become non-JavaThreads, add them here
}
// All JavaThreads