8209975: Some GCThreadLocalData not initialized
authorkbarrett
Thu, 30 Aug 2018 17:03:46 -0400
changeset 51600 56309b1b9d9b
parent 51599 3198179d97fa
child 51601 e469480420dc
8209975: Some GCThreadLocalData not initialized Summary: Perform deferred BarrierSet initializations for NonJavaThreads too. Reviewed-by: eosterlund, pliden
src/hotspot/share/gc/shared/barrierSet.cpp
src/hotspot/share/runtime/thread.cpp
src/hotspot/share/runtime/thread.hpp
--- 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();