mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 10:04:42 +02:00
8233281: Obsolete UseSemaphoreGCThreadsSynchronization
Reviewed-by: tschatzl, kbarrett, ayang
This commit is contained in:
parent
55e3560abc
commit
ea73b5b0d9
4 changed files with 15 additions and 110 deletions
|
@ -174,10 +174,6 @@
|
||||||
"Number of parallel threads parallel gc will use") \
|
"Number of parallel threads parallel gc will use") \
|
||||||
constraint(ParallelGCThreadsConstraintFunc,AfterErgo) \
|
constraint(ParallelGCThreadsConstraintFunc,AfterErgo) \
|
||||||
\
|
\
|
||||||
diagnostic(bool, UseSemaphoreGCThreadsSynchronization, true, \
|
|
||||||
"Use semaphore synchronization for the GC Threads, " \
|
|
||||||
"instead of synchronization based on mutexes") \
|
|
||||||
\
|
|
||||||
product(bool, UseDynamicNumberOfGCThreads, true, \
|
product(bool, UseDynamicNumberOfGCThreads, true, \
|
||||||
"Dynamically choose the number of threads up to a maximum of " \
|
"Dynamically choose the number of threads up to a maximum of " \
|
||||||
"ParallelGCThreads parallel collectors will use for garbage " \
|
"ParallelGCThreads parallel collectors will use for garbage " \
|
||||||
|
|
|
@ -109,7 +109,7 @@ static void run_foreground_task_if_needed(AbstractGangTask* task, uint num_worke
|
||||||
//
|
//
|
||||||
// Semaphores don't require the worker threads to re-claim the lock when they wake up.
|
// 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.
|
// This helps lowering the latency when starting and stopping the worker threads.
|
||||||
class SemaphoreGangTaskDispatcher : public GangTaskDispatcher {
|
class GangTaskDispatcher : public CHeapObj<mtGC> {
|
||||||
// The task currently being dispatched to the GangWorkers.
|
// The task currently being dispatched to the GangWorkers.
|
||||||
AbstractGangTask* _task;
|
AbstractGangTask* _task;
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ class SemaphoreGangTaskDispatcher : public GangTaskDispatcher {
|
||||||
Semaphore* _end_semaphore;
|
Semaphore* _end_semaphore;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SemaphoreGangTaskDispatcher() :
|
GangTaskDispatcher() :
|
||||||
_task(NULL),
|
_task(NULL),
|
||||||
_started(0),
|
_started(0),
|
||||||
_not_finished(0),
|
_not_finished(0),
|
||||||
|
@ -130,11 +130,15 @@ public:
|
||||||
_end_semaphore(new Semaphore())
|
_end_semaphore(new Semaphore())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
~SemaphoreGangTaskDispatcher() {
|
~GangTaskDispatcher() {
|
||||||
delete _start_semaphore;
|
delete _start_semaphore;
|
||||||
delete _end_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) {
|
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.
|
// No workers are allowed to read the state variables until they have been signaled.
|
||||||
_task = task;
|
_task = task;
|
||||||
|
@ -155,6 +159,10 @@ public:
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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() {
|
WorkData worker_wait_for_task() {
|
||||||
// Wait for the coordinator to dispatch a task.
|
// Wait for the coordinator to dispatch a task.
|
||||||
_start_semaphore->wait();
|
_start_semaphore->wait();
|
||||||
|
@ -167,6 +175,7 @@ public:
|
||||||
return WorkData(_task, worker_id);
|
return WorkData(_task, worker_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Signal to the coordinator that the worker is done with the assigned task.
|
||||||
void worker_done_with_task() {
|
void worker_done_with_task() {
|
||||||
// Mark that the worker is done with the task.
|
// Mark that the worker is done with the task.
|
||||||
// The worker is not allowed to read the state variables after this line.
|
// The worker is not allowed to read the state variables after this line.
|
||||||
|
@ -179,91 +188,12 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
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,
|
WorkGang::WorkGang(const char* name,
|
||||||
uint workers,
|
uint workers,
|
||||||
bool are_GC_task_threads,
|
bool are_GC_task_threads,
|
||||||
bool are_ConcurrentGC_threads) :
|
bool are_ConcurrentGC_threads) :
|
||||||
AbstractWorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads),
|
AbstractWorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads),
|
||||||
_dispatcher(create_dispatcher())
|
_dispatcher(new GangTaskDispatcher())
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
WorkGang::~WorkGang() {
|
WorkGang::~WorkGang() {
|
||||||
|
|
|
@ -52,6 +52,7 @@ class AbstractGangWorker;
|
||||||
class Semaphore;
|
class Semaphore;
|
||||||
class ThreadClosure;
|
class ThreadClosure;
|
||||||
class WorkGang;
|
class WorkGang;
|
||||||
|
class GangTaskDispatcher;
|
||||||
|
|
||||||
// An abstract task to be worked on by a gang.
|
// An abstract task to be worked on by a gang.
|
||||||
// You subclass this to supply your own work() method
|
// You subclass this to supply your own work() method
|
||||||
|
@ -80,29 +81,6 @@ struct WorkData {
|
||||||
WorkData(AbstractGangTask* task, uint worker_id) : _task(task), _worker_id(worker_id) {}
|
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<mtGC> {
|
|
||||||
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 work gang is the collection of workers to execute tasks.
|
||||||
// The number of workers run for a task is "_active_workers"
|
// The number of workers run for a task is "_active_workers"
|
||||||
// while "_total_workers" is the number of available of workers.
|
// while "_total_workers" is the number of available of workers.
|
||||||
|
|
|
@ -552,6 +552,7 @@ static SpecialFlag const special_jvm_flags[] = {
|
||||||
#endif
|
#endif
|
||||||
{ "PrintVMQWaitTime", JDK_Version::jdk(15), JDK_Version::jdk(16), JDK_Version::jdk(17) },
|
{ "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) },
|
{ "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
|
#ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS
|
||||||
// These entries will generate build errors. Their purpose is to test the macros.
|
// These entries will generate build errors. Their purpose is to test the macros.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue