# HG changeset patch # User kbarrett # Date 1535663026 14400 # Node ID 56309b1b9d9b151adf057a8f79ead36c0bce45f1 # Parent 3198179d97fa1ba1a2b82c9b49650b444a8cfaa5 8209975: Some GCThreadLocalData not initialized Summary: Perform deferred BarrierSet initializations for NonJavaThreads too. Reviewed-by: eosterlund, pliden diff -r 3198179d97fa -r 56309b1b9d9b src/hotspot/share/gc/shared/barrierSet.cpp --- a/src/hotspot/share/gc/shared/barrierSet.cpp Thu Aug 30 16:33:14 2018 -0400 +++ b/src/hotspot/share/gc/shared/barrierSet.cpp Thu Aug 30 17:03:46 2018 -0400 @@ -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()); } diff -r 3198179d97fa -r 56309b1b9d9b src/hotspot/share/runtime/thread.cpp --- a/src/hotspot/share/runtime/thread.cpp Thu Aug 30 16:33:14 2018 -0400 +++ b/src/hotspot/share/runtime/thread.cpp Thu Aug 30 17:03:46 2018 -0400 @@ -307,13 +307,15 @@ } #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 @@ #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) { diff -r 3198179d97fa -r 56309b1b9d9b src/hotspot/share/runtime/thread.hpp --- a/src/hotspot/share/runtime/thread.hpp Thu Aug 30 16:33:14 2018 -0400 +++ b/src/hotspot/share/runtime/thread.hpp Thu Aug 30 17:03:46 2018 -0400 @@ -2146,6 +2146,7 @@ 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 @@ #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();