8209975: Some GCThreadLocalData not initialized
Summary: Perform deferred BarrierSet initializations for NonJavaThreads too.
Reviewed-by: eosterlund, pliden
--- 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());
}
--- 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) {
--- 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();