8215487: ZGC: ZRuntimeWorkers incorrectly identify themselves as ZWorkers
authorpliden
Wed, 19 Dec 2018 08:32:48 +0100
changeset 53072 82d3f0820d37
parent 53071 281c85f43f79
child 53073 11033c4ada54
child 53082 4c539cb11633
8215487: ZGC: ZRuntimeWorkers incorrectly identify themselves as ZWorkers Reviewed-by: eosterlund
src/hotspot/share/gc/z/zObjectAllocator.cpp
src/hotspot/share/gc/z/zRuntimeWorkers.cpp
src/hotspot/share/gc/z/zThread.cpp
src/hotspot/share/gc/z/zThread.hpp
src/hotspot/share/gc/z/zWorkers.cpp
--- a/src/hotspot/share/gc/z/zObjectAllocator.cpp	Tue Dec 18 13:37:06 2018 -0800
+++ b/src/hotspot/share/gc/z/zObjectAllocator.cpp	Wed Dec 19 08:32:48 2018 +0100
@@ -128,7 +128,8 @@
 }
 
 uintptr_t ZObjectAllocator::alloc_small_object_from_nonworker(size_t size, ZAllocationFlags flags) {
-  assert(ZThread::is_java() || ZThread::is_vm(), "Should be a Java or VM thread");
+  assert(ZThread::is_java() || ZThread::is_vm() || ZThread::is_runtime_worker(),
+         "Should be a Java, VM or Runtime worker thread");
 
   // Non-worker small page allocation can never use the reserve
   flags.set_no_reserve();
@@ -193,7 +194,8 @@
 }
 
 uintptr_t ZObjectAllocator::alloc_object_for_relocation(size_t size) {
-  assert(ZThread::is_java() || ZThread::is_worker() || ZThread::is_vm(), "Unknown thread");
+  assert(ZThread::is_java() || ZThread::is_vm() || ZThread::is_worker() || ZThread::is_runtime_worker(),
+         "Unknown thread");
 
   ZAllocationFlags flags;
   flags.set_relocation();
--- a/src/hotspot/share/gc/z/zRuntimeWorkers.cpp	Tue Dec 18 13:37:06 2018 -0800
+++ b/src/hotspot/share/gc/z/zRuntimeWorkers.cpp	Wed Dec 19 08:32:48 2018 +0100
@@ -22,7 +22,43 @@
  */
 
 #include "precompiled.hpp"
+#include "gc/shared/workgroup.hpp"
 #include "gc/z/zRuntimeWorkers.hpp"
+#include "gc/z/zThread.hpp"
+#include "runtime/mutexLocker.hpp"
+
+class ZRuntimeWorkersInitializeTask : public AbstractGangTask {
+private:
+  const uint _nworkers;
+  uint       _started;
+  Monitor    _monitor;
+
+public:
+  ZRuntimeWorkersInitializeTask(uint nworkers) :
+      AbstractGangTask("ZRuntimeWorkersInitializeTask"),
+      _nworkers(nworkers),
+      _started(0),
+      _monitor(Monitor::leaf,
+               "ZRuntimeWorkersInitialize",
+               false /* allow_vm_block */,
+               Monitor::_safepoint_check_never) {}
+
+  virtual void work(uint worker_id) {
+    // Register as runtime worker
+    ZThread::set_runtime_worker();
+
+    // Wait for all threads to start
+    MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
+    if (++_started == _nworkers) {
+      // All threads started
+      ml.notify_all();
+    } else {
+      while (_started != _nworkers) {
+        ml.wait(Monitor::_no_safepoint_check_flag);
+      }
+    }
+  }
+};
 
 ZRuntimeWorkers::ZRuntimeWorkers() :
     _workers("RuntimeWorker",
@@ -35,6 +71,15 @@
   // Initialize worker threads
   _workers.initialize_workers();
   _workers.update_active_workers(nworkers());
+  if (_workers.active_workers() != nworkers()) {
+    vm_exit_during_initialization("Failed to create ZRuntimeWorkers");
+  }
+
+  // Execute task to register threads as runtime workers. This also
+  // helps reduce latency in early safepoints, which otherwise would
+  // have to take on any warmup costs.
+  ZRuntimeWorkersInitializeTask task(nworkers());
+  _workers.run_task(&task);
 }
 
 uint ZRuntimeWorkers::nworkers() const {
--- a/src/hotspot/share/gc/z/zThread.cpp	Tue Dec 18 13:37:06 2018 -0800
+++ b/src/hotspot/share/gc/z/zThread.cpp	Wed Dec 19 08:32:48 2018 +0100
@@ -31,6 +31,7 @@
 __thread bool      ZThread::_is_vm;
 __thread bool      ZThread::_is_java;
 __thread bool      ZThread::_is_worker;
+__thread bool      ZThread::_is_runtime_worker;
 __thread uint      ZThread::_worker_id;
 
 void ZThread::initialize() {
@@ -40,7 +41,8 @@
   _id = (uintptr_t)thread;
   _is_vm = thread->is_VM_thread();
   _is_java = thread->is_Java_thread();
-  _is_worker = thread->is_Worker_thread();
+  _is_worker = false;
+  _is_runtime_worker = false;
   _worker_id = (uint)-1;
 }
 
@@ -56,6 +58,16 @@
   return "Unknown";
 }
 
+void ZThread::set_worker() {
+  ensure_initialized();
+  _is_worker = true;
+}
+
+void ZThread::set_runtime_worker() {
+  ensure_initialized();
+  _is_runtime_worker = true;
+}
+
 bool ZThread::has_worker_id() {
   return _initialized &&
          _is_worker &&
--- a/src/hotspot/share/gc/z/zThread.hpp	Tue Dec 18 13:37:06 2018 -0800
+++ b/src/hotspot/share/gc/z/zThread.hpp	Wed Dec 19 08:32:48 2018 +0100
@@ -29,6 +29,8 @@
 
 class ZThread : public AllStatic {
   friend class ZTask;
+  friend class ZWorkersInitializeTask;
+  friend class ZRuntimeWorkersInitializeTask;
 
 private:
   static __thread bool      _initialized;
@@ -36,6 +38,7 @@
   static __thread bool      _is_vm;
   static __thread bool      _is_java;
   static __thread bool      _is_worker;
+  static __thread bool      _is_runtime_worker;
   static __thread uint      _worker_id;
 
   static void initialize();
@@ -46,6 +49,9 @@
     }
   }
 
+  static void set_worker();
+  static void set_runtime_worker();
+
   static bool has_worker_id();
   static void set_worker_id(uint worker_id);
   static void clear_worker_id();
@@ -73,6 +79,11 @@
     return _is_worker;
   }
 
+  static bool is_runtime_worker() {
+    ensure_initialized();
+    return _is_runtime_worker;
+  }
+
   static uint worker_id() {
     assert(has_worker_id(), "Worker id not initialized");
     return _worker_id;
--- a/src/hotspot/share/gc/z/zWorkers.cpp	Tue Dec 18 13:37:06 2018 -0800
+++ b/src/hotspot/share/gc/z/zWorkers.cpp	Wed Dec 19 08:32:48 2018 +0100
@@ -24,6 +24,7 @@
 #include "precompiled.hpp"
 #include "gc/z/zGlobals.hpp"
 #include "gc/z/zTask.hpp"
+#include "gc/z/zThread.hpp"
 #include "gc/z/zWorkers.inline.hpp"
 #include "runtime/os.hpp"
 #include "runtime/mutexLocker.hpp"
@@ -64,20 +65,26 @@
   return calculate_nworkers(12.5);
 }
 
-class ZWorkersWarmupTask : public ZTask {
+class ZWorkersInitializeTask : public ZTask {
 private:
   const uint _nworkers;
   uint       _started;
   Monitor    _monitor;
 
 public:
-  ZWorkersWarmupTask(uint nworkers) :
-      ZTask("ZWorkersWarmupTask"),
+  ZWorkersInitializeTask(uint nworkers) :
+      ZTask("ZWorkersInitializeTask"),
       _nworkers(nworkers),
       _started(0),
-      _monitor(Monitor::leaf, "ZWorkersWarmup", false, Monitor::_safepoint_check_never) {}
+      _monitor(Monitor::leaf,
+               "ZWorkersInitialize",
+               false /* allow_vm_block */,
+               Monitor::_safepoint_check_never) {}
 
   virtual void work() {
+    // Register as worker
+    ZThread::set_worker();
+
     // Wait for all threads to start
     MonitorLockerEx ml(&_monitor, Monitor::_no_safepoint_check_flag);
     if (++_started == _nworkers) {
@@ -107,10 +114,10 @@
     vm_exit_during_initialization("Failed to create ZWorkers");
   }
 
-  // Warm up worker threads by having them execute a dummy task.
-  // This helps reduce latency in early GC pauses, which otherwise
-  // would have to take on any warmup costs.
-  ZWorkersWarmupTask task(nworkers());
+  // Execute task to register threads as workers. This also helps
+  // reduce latency in early GC pauses, which otherwise would have
+  // to take on any warmup costs.
+  ZWorkersInitializeTask task(nworkers());
   run(&task, nworkers());
 }