8209975: Some GCThreadLocalData not initialized

Perform deferred BarrierSet initializations for NonJavaThreads too.

Reviewed-by: eosterlund, pliden
This commit is contained in:
Kim Barrett 2018-08-30 17:03:46 -04:00
parent 26560a934d
commit 6a0bb0955e
3 changed files with 52 additions and 8 deletions

View file

@ -30,13 +30,45 @@
BarrierSet* BarrierSet::_barrier_set = NULL;
class SetBarrierSetNonJavaThread : public ThreadClosure {
BarrierSet* _barrier_set;
size_t _count;
public:
SetBarrierSetNonJavaThread(BarrierSet* barrier_set) :
_barrier_set(barrier_set), _count(0) {}
virtual void do_thread(Thread* thread) {
_barrier_set->on_thread_create(thread);
++_count;
}
size_t count() const { return _count; }
};
void BarrierSet::set_barrier_set(BarrierSet* barrier_set) {
assert(_barrier_set == NULL, "Already initialized");
_barrier_set = barrier_set;
// The barrier set was not initialized when the this thread (the main thread)
// was created, so the call to BarrierSet::on_thread_create() had to be deferred
// until we have a barrier set. Now we have a barrier set, so we make the call.
// Some threads are created before the barrier set, so the call to
// BarrierSet::on_thread_create had to be deferred for them. Now that
// we have the barrier set, do those deferred calls.
// First do any non-JavaThreads.
SetBarrierSetNonJavaThread njt_closure(_barrier_set);
Threads::non_java_threads_do(&njt_closure);
// Do the current (main) thread. Ensure it's the one and only
// JavaThread so far. Also verify that it isn't yet on the thread
// list, else we'd also need to call BarrierSet::on_thread_attach.
assert(Thread::current()->is_Java_thread(),
"Expected main thread to be a JavaThread");
assert((njt_closure.count() + 1) == Threads::threads_before_barrier_set(),
"Unexpected JavaThreads before barrier set initialization: "
"Non-JavaThreads: " SIZE_FORMAT ", all: " SIZE_FORMAT,
njt_closure.count(), Threads::threads_before_barrier_set());
assert(!JavaThread::current()->on_thread_list(),
"Main thread already on thread list.");
_barrier_set->on_thread_create(Thread::current());
}

View file

@ -307,13 +307,15 @@ Thread::Thread() {
}
#endif // ASSERT
// Notify the barrier set that a thread is being created. Note that the
// main thread is created before a barrier set is available. The call to
// BarrierSet::on_thread_create() for the main thread is therefore deferred
// until it calls BarrierSet::set_barrier_set().
// Notify the barrier set that a thread is being created. Note that some
// threads are created before a barrier set is available. The call to
// BarrierSet::on_thread_create() for these threads is therefore deferred
// to BarrierSet::set_barrier_set().
BarrierSet* const barrier_set = BarrierSet::barrier_set();
if (barrier_set != NULL) {
barrier_set->on_thread_create(this);
} else {
DEBUG_ONLY(Threads::inc_threads_before_barrier_set();)
}
}
@ -3397,6 +3399,7 @@ size_t JavaThread::_stack_size_at_create = 0;
#ifdef ASSERT
bool Threads::_vm_complete = false;
size_t Threads::_threads_before_barrier_set = 0;
#endif
static inline void *prefetch_and_load_ptr(void **addr, intx prefetch_interval) {

View file

@ -2146,6 +2146,7 @@ class Threads: AllStatic {
static int _thread_claim_parity;
#ifdef ASSERT
static bool _vm_complete;
static size_t _threads_before_barrier_set;
#endif
static void initialize_java_lang_classes(JavaThread* main_thread, TRAPS);
@ -2215,7 +2216,15 @@ class Threads: AllStatic {
#ifdef ASSERT
static bool is_vm_complete() { return _vm_complete; }
#endif
static size_t threads_before_barrier_set() {
return _threads_before_barrier_set;
}
static void inc_threads_before_barrier_set() {
++_threads_before_barrier_set;
}
#endif // ASSERT
// Verification
static void verify();