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") \
|
||||
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 " \
|
||||
|
|
|
@ -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.
|
||||
// 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.
|
||||
AbstractGangTask* _task;
|
||||
|
||||
|
@ -122,7 +122,7 @@ class SemaphoreGangTaskDispatcher : public GangTaskDispatcher {
|
|||
Semaphore* _end_semaphore;
|
||||
|
||||
public:
|
||||
SemaphoreGangTaskDispatcher() :
|
||||
GangTaskDispatcher() :
|
||||
_task(NULL),
|
||||
_started(0),
|
||||
_not_finished(0),
|
||||
|
@ -130,11 +130,15 @@ public:
|
|||
_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 @@ 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() {
|
||||
// Wait for the coordinator to dispatch a task.
|
||||
_start_semaphore->wait();
|
||||
|
@ -167,6 +175,7 @@ public:
|
|||
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 @@ 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,
|
||||
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() {
|
||||
|
|
|
@ -52,6 +52,7 @@ class AbstractGangWorker;
|
|||
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 @@ struct WorkData {
|
|||
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 number of workers run for a task is "_active_workers"
|
||||
// while "_total_workers" is the number of available of workers.
|
||||
|
|
|
@ -552,6 +552,7 @@ static SpecialFlag const special_jvm_flags[] = {
|
|||
#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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue