8215487: ZGC: ZRuntimeWorkers incorrectly identify themselves as ZWorkers
Reviewed-by: eosterlund
--- 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());
}