mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-17 17:44:40 +02:00
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:
parent
1ddabdf0dc
commit
e1059f1301
8 changed files with 107 additions and 121 deletions
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue