--- old/src/hotspot/share/gc/shared/gc_globals.hpp 2020-08-14 16:28:41.609439476 +0200 +++ new/src/hotspot/share/gc/shared/gc_globals.hpp 2020-08-14 16:28:41.349434842 +0200 @@ -174,10 +174,6 @@ "Number of parallel threads parallel gc will use") \ constraint(ParallelGCThreadsConstraintFunc,AfterErgo) \ \ - diagnostic(bool, UseSemaphoreGCThreadsSynchronization, true, \ - "Use semaphore synchronization for the GC Threads, " \ - "instead of synchronization based on mutexes") \ - \ product(bool, UseDynamicNumberOfGCThreads, true, \ "Dynamically choose the number of threads up to a maximum of " \ "ParallelGCThreads parallel collectors will use for garbage " \ --- old/src/hotspot/share/gc/shared/workgroup.cpp 2020-08-14 16:28:42.049447320 +0200 +++ new/src/hotspot/share/gc/shared/workgroup.cpp 2020-08-14 16:28:41.833443470 +0200 @@ -109,7 +109,7 @@ // // Semaphores don't require the worker threads to re-claim the lock when they wake up. // This helps lowering the latency when starting and stopping the worker threads. -class SemaphoreGangTaskDispatcher : public GangTaskDispatcher { +class GangTaskDispatcher : public CHeapObj { // The task currently being dispatched to the GangWorkers. AbstractGangTask* _task; @@ -122,7 +122,7 @@ Semaphore* _end_semaphore; public: - SemaphoreGangTaskDispatcher() : + GangTaskDispatcher() : _task(NULL), _started(0), _not_finished(0), @@ -130,11 +130,15 @@ _end_semaphore(new Semaphore()) { } - ~SemaphoreGangTaskDispatcher() { + ~GangTaskDispatcher() { delete _start_semaphore; delete _end_semaphore; } + // Coordinator API. + + // Distributes the task out to num_workers workers. + // Returns when the task has been completed by all workers. void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers, bool add_foreground_work) { // No workers are allowed to read the state variables until they have been signaled. _task = task; @@ -155,6 +159,10 @@ } + // Worker API. + + // Waits for a task to become available to the worker. + // Returns when the worker has been assigned a task. WorkData worker_wait_for_task() { // Wait for the coordinator to dispatch a task. _start_semaphore->wait(); @@ -167,6 +175,7 @@ return WorkData(_task, worker_id); } + // Signal to the coordinator that the worker is done with the assigned task. void worker_done_with_task() { // Mark that the worker is done with the task. // The worker is not allowed to read the state variables after this line. @@ -179,91 +188,12 @@ } }; -class MutexGangTaskDispatcher : public GangTaskDispatcher { - AbstractGangTask* _task; - - volatile uint _started; - volatile uint _finished; - volatile uint _num_workers; - - Monitor* _monitor; - - public: - MutexGangTaskDispatcher() : - _task(NULL), - _started(0), - _finished(0), - _num_workers(0), - _monitor(new Monitor(Monitor::leaf, "WorkGang dispatcher lock", false, Monitor::_safepoint_check_never)) { - } - - ~MutexGangTaskDispatcher() { - delete _monitor; - } - - void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers, bool add_foreground_work) { - MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag); - - _task = task; - _num_workers = num_workers; - - // Tell the workers to get to work. - _monitor->notify_all(); - - run_foreground_task_if_needed(task, num_workers, add_foreground_work); - - // Wait for them to finish. - while (_finished < _num_workers) { - ml.wait(); - } - - _task = NULL; - _num_workers = 0; - _started = 0; - _finished = 0; - } - - WorkData worker_wait_for_task() { - MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag); - - while (_num_workers == 0 || _started == _num_workers) { - _monitor->wait(); - } - - _started++; - - // Subtract one to get a zero-indexed worker id. - uint worker_id = _started - 1; - - return WorkData(_task, worker_id); - } - - void worker_done_with_task() { - MonitorLocker ml(_monitor, Mutex::_no_safepoint_check_flag); - - _finished++; - - if (_finished == _num_workers) { - // This will wake up all workers and not only the coordinator. - _monitor->notify_all(); - } - } -}; - -static GangTaskDispatcher* create_dispatcher() { - if (UseSemaphoreGCThreadsSynchronization) { - return new SemaphoreGangTaskDispatcher(); - } - - return new MutexGangTaskDispatcher(); -} - WorkGang::WorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads) : AbstractWorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads), - _dispatcher(create_dispatcher()) + _dispatcher(new GangTaskDispatcher()) { } WorkGang::~WorkGang() { --- old/src/hotspot/share/gc/shared/workgroup.hpp 2020-08-14 16:28:43.649475843 +0200 +++ new/src/hotspot/share/gc/shared/workgroup.hpp 2020-08-14 16:28:43.393471280 +0200 @@ -52,6 +52,7 @@ class Semaphore; class ThreadClosure; class WorkGang; +class GangTaskDispatcher; // An abstract task to be worked on by a gang. // You subclass this to supply your own work() method @@ -80,29 +81,6 @@ WorkData(AbstractGangTask* task, uint worker_id) : _task(task), _worker_id(worker_id) {} }; -// Interface to handle the synchronization between the coordinator thread and the worker threads, -// when a task is dispatched out to the worker threads. -class GangTaskDispatcher : public CHeapObj { - public: - virtual ~GangTaskDispatcher() {} - - // Coordinator API. - - // Distributes the task out to num_workers workers. - // Returns when the task has been completed by all workers. - virtual void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers, - bool add_foreground_work) = 0; - - // Worker API. - - // Waits for a task to become available to the worker. - // Returns when the worker has been assigned a task. - virtual WorkData worker_wait_for_task() = 0; - - // Signal to the coordinator that the worker is done with the assigned task. - virtual void worker_done_with_task() = 0; -}; - // The work gang is the collection of workers to execute tasks. // The number of workers run for a task is "_active_workers" // while "_total_workers" is the number of available of workers. --- old/src/hotspot/share/runtime/arguments.cpp 2020-08-14 16:28:45.285505008 +0200 +++ new/src/hotspot/share/runtime/arguments.cpp 2020-08-14 16:28:45.065501086 +0200 @@ -552,6 +552,7 @@ #endif { "PrintVMQWaitTime", JDK_Version::jdk(15), JDK_Version::jdk(16), JDK_Version::jdk(17) }, { "UseNewFieldLayout", JDK_Version::jdk(15), JDK_Version::jdk(16), JDK_Version::jdk(17) }, + { "UseSemaphoreGCThreadsSynchronization", JDK_Version::undefined(), JDK_Version::jdk(16), JDK_Version::jdk(17) }, #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS // These entries will generate build errors. Their purpose is to test the macros.