8275035: Clean up worker thread infrastructure
Reviewed-by: stefank, ayang
This commit is contained in:
parent
3b0b6adc3d
commit
54b8870766
src/hotspot/share
gc
epsilon
g1
g1BatchedTask.cppg1BatchedTask.hppg1CollectedHeap.cppg1CollectedHeap.hppg1CollectionSetCandidates.hppg1CollectionSetChooser.cppg1CollectionSetChooser.hppg1ConcurrentMark.cppg1ConcurrentMark.hppg1EvacFailure.cppg1EvacFailure.hppg1FullCollector.cppg1FullCollector.hppg1FullGCTask.hppg1HeapVerifier.cppg1PageBasedVirtualSpace.cppg1PageBasedVirtualSpace.hppg1ParallelCleaning.cppg1ParallelCleaning.hppg1RegionToSpaceMapper.cppg1RegionToSpaceMapper.hppg1RemSet.cppg1RemSet.hppg1YoungCollector.cppg1YoungCollector.hppg1YoungGCPostEvacuateTasks.cppg1YoungGCPostEvacuateTasks.hppheapRegionManager.cppheapRegionManager.hpp
parallel
mutableNUMASpace.cppmutableNUMASpace.hppmutableSpace.cppmutableSpace.hppparallelScavengeHeap.cppparallelScavengeHeap.hpppsCompactionManager.cpppsOldGen.cpppsParallelCompact.cpppsScavenge.cpppsYoungGen.cpp
shared
collectedHeap.hppgenCollectedHeap.cppgenCollectedHeap.hppparallelCleaning.hpppreservedMarks.cpppreservedMarks.hpppretouchTask.cpppretouchTask.hppreferenceProcessor.cppreferenceProcessor.hppspace.hppweakProcessor.cppweakProcessor.hppweakProcessor.inline.hppworkerManager.hppworkerThread.cppworkerThread.hppworkerUtils.cppworkerUtils.hppworkgroup.cppworkgroup.hpp
shenandoah
shenandoahCodeRoots.cppshenandoahCodeRoots.hppshenandoahConcurrentGC.cppshenandoahConcurrentMark.cppshenandoahFullGC.cppshenandoahGC.cppshenandoahHeap.cppshenandoahHeap.hppshenandoahHeap.inline.hppshenandoahParallelCleaning.cppshenandoahParallelCleaning.hppshenandoahParallelCleaning.inline.hppshenandoahReferenceProcessor.cppshenandoahReferenceProcessor.hppshenandoahSTWMark.cppshenandoahVerifier.cppshenandoahWorkGroup.cppshenandoahWorkGroup.hpp
z
logging
memory
runtime
services
test/hotspot/gtest/gc/g1
@ -27,6 +27,7 @@
|
||||
#include "gc/epsilon/epsilonHeap.hpp"
|
||||
#include "gc/shared/gcArguments.hpp"
|
||||
#include "gc/shared/tlab_globals.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/globals_extension.hpp"
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "gc/epsilon/epsilonThreadLocalData.hpp"
|
||||
#include "gc/shared/gcArguments.hpp"
|
||||
#include "gc/shared/locationPrinter.inline.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/metaspaceUtils.hpp"
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "gc/g1/g1BatchedGangTask.hpp"
|
||||
#include "gc/g1/g1BatchedTask.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1GCParPhaseTimesTracker.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
@ -40,30 +40,30 @@ const char* G1AbstractSubTask::name() const {
|
||||
return g1h->phase_times()->phase_name(_tag);
|
||||
}
|
||||
|
||||
bool G1BatchedGangTask::try_claim_serial_task(int& task) {
|
||||
bool G1BatchedTask::try_claim_serial_task(int& task) {
|
||||
task = Atomic::fetch_and_add(&_num_serial_tasks_done, 1);
|
||||
return task < _serial_tasks.length();
|
||||
}
|
||||
|
||||
void G1BatchedGangTask::add_serial_task(G1AbstractSubTask* task) {
|
||||
void G1BatchedTask::add_serial_task(G1AbstractSubTask* task) {
|
||||
assert(task != nullptr, "must be");
|
||||
_serial_tasks.push(task);
|
||||
}
|
||||
|
||||
void G1BatchedGangTask::add_parallel_task(G1AbstractSubTask* task) {
|
||||
void G1BatchedTask::add_parallel_task(G1AbstractSubTask* task) {
|
||||
assert(task != nullptr, "must be");
|
||||
_parallel_tasks.push(task);
|
||||
}
|
||||
|
||||
G1BatchedGangTask::G1BatchedGangTask(const char* name, G1GCPhaseTimes* phase_times) :
|
||||
AbstractGangTask(name),
|
||||
G1BatchedTask::G1BatchedTask(const char* name, G1GCPhaseTimes* phase_times) :
|
||||
WorkerTask(name),
|
||||
_num_serial_tasks_done(0),
|
||||
_phase_times(phase_times),
|
||||
_serial_tasks(),
|
||||
_parallel_tasks() {
|
||||
}
|
||||
|
||||
uint G1BatchedGangTask::num_workers_estimate() const {
|
||||
uint G1BatchedTask::num_workers_estimate() const {
|
||||
double sum = 0.0;
|
||||
for (G1AbstractSubTask* task : _serial_tasks) {
|
||||
sum += task->worker_cost();
|
||||
@ -74,7 +74,7 @@ uint G1BatchedGangTask::num_workers_estimate() const {
|
||||
return ceil(sum);
|
||||
}
|
||||
|
||||
void G1BatchedGangTask::set_max_workers(uint max_workers) {
|
||||
void G1BatchedTask::set_max_workers(uint max_workers) {
|
||||
for (G1AbstractSubTask* task : _serial_tasks) {
|
||||
task->set_max_workers(max_workers);
|
||||
}
|
||||
@ -83,7 +83,7 @@ void G1BatchedGangTask::set_max_workers(uint max_workers) {
|
||||
}
|
||||
}
|
||||
|
||||
void G1BatchedGangTask::work(uint worker_id) {
|
||||
void G1BatchedTask::work(uint worker_id) {
|
||||
int t = 0;
|
||||
while (try_claim_serial_task(t)) {
|
||||
G1AbstractSubTask* task = _serial_tasks.at(t);
|
||||
@ -96,7 +96,7 @@ void G1BatchedGangTask::work(uint worker_id) {
|
||||
}
|
||||
}
|
||||
|
||||
G1BatchedGangTask::~G1BatchedGangTask() {
|
||||
G1BatchedTask::~G1BatchedTask() {
|
||||
assert(Atomic::load(&_num_serial_tasks_done) >= _serial_tasks.length(),
|
||||
"Only %d tasks of %d claimed", Atomic::load(&_num_serial_tasks_done), _serial_tasks.length());
|
||||
|
@ -22,18 +22,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_G1_G1BATCHEDGANGTASK_HPP
|
||||
#define SHARE_GC_G1_G1BATCHEDGANGTASK_HPP
|
||||
#ifndef SHARE_GC_G1_G1BATCHEDTASK_HPP
|
||||
#define SHARE_GC_G1_G1BATCHEDTASK_HPP
|
||||
|
||||
#include "gc/g1/g1GCPhaseTimes.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
template <typename E, MEMFLAGS F>
|
||||
class GrowableArrayCHeap;
|
||||
|
||||
// G1AbstractSubTask represents a task to be performed either within a
|
||||
// G1BatchedGangTask running on a single worker ("serially") or multiple workers
|
||||
// G1BatchedTask running on a single worker ("serially") or multiple workers
|
||||
// ("in parallel"). A G1AbstractSubTask is always associated with a phase tag
|
||||
// that is used to automatically store timing information.
|
||||
//
|
||||
@ -46,7 +46,7 @@ class GrowableArrayCHeap;
|
||||
// splits across the heap in some way. Current examples would be clearing the
|
||||
// card table.
|
||||
//
|
||||
// See G1BatchedGangTask for information on execution.
|
||||
// See G1BatchedTask for information on execution.
|
||||
class G1AbstractSubTask : public CHeapObj<mtGC> {
|
||||
G1GCPhaseTimes::GCParPhases _tag;
|
||||
|
||||
@ -65,10 +65,10 @@ public:
|
||||
|
||||
// How many workers (threads) would this task be able to keep busy for at least
|
||||
// as long as to amortize worker startup costs.
|
||||
// Called by G1BatchedGangTask to determine total number of workers.
|
||||
// Called by G1BatchedTask to determine total number of workers.
|
||||
virtual double worker_cost() const = 0;
|
||||
|
||||
// Called by G1BatchedGangTask to provide information about the the maximum
|
||||
// Called by G1BatchedTask to provide information about the the maximum
|
||||
// number of workers for all subtasks after it has been determined.
|
||||
virtual void set_max_workers(uint max_workers) { }
|
||||
|
||||
@ -81,7 +81,7 @@ public:
|
||||
const char* name() const;
|
||||
};
|
||||
|
||||
// G1BatchedGangTask runs a set of G1AbstractSubTask using a work gang.
|
||||
// G1BatchedTask runs a set of G1AbstractSubTask using workers.
|
||||
//
|
||||
// Subclasses of this class add their G1AbstractSubTasks into either the list
|
||||
// of "serial" or the list of "parallel" tasks. They are supposed to be the owners
|
||||
@ -94,7 +94,7 @@ public:
|
||||
// add_parallel_task(new SomeOtherSubTask());
|
||||
// [...]
|
||||
//
|
||||
// During execution in the work gang, this class will make sure that the "serial"
|
||||
// During execution in workers, this class will make sure that the "serial"
|
||||
// tasks are executed by a single worker exactly once, but different "serial"
|
||||
// tasks may be executed in parallel using different workers. "Parallel" tasks'
|
||||
// do_work() method may be called by different workers passing a different
|
||||
@ -119,13 +119,13 @@ public:
|
||||
// 4) T::do_work() // potentially in parallel with any other registered G1AbstractSubTask
|
||||
// 5) ~T()
|
||||
//
|
||||
class G1BatchedGangTask : public AbstractGangTask {
|
||||
class G1BatchedTask : public WorkerTask {
|
||||
volatile int _num_serial_tasks_done;
|
||||
G1GCPhaseTimes* _phase_times;
|
||||
|
||||
bool try_claim_serial_task(int& task);
|
||||
|
||||
NONCOPYABLE(G1BatchedGangTask);
|
||||
NONCOPYABLE(G1BatchedTask);
|
||||
|
||||
GrowableArrayCHeap<G1AbstractSubTask*, mtGC> _serial_tasks;
|
||||
GrowableArrayCHeap<G1AbstractSubTask*, mtGC> _parallel_tasks;
|
||||
@ -134,19 +134,19 @@ protected:
|
||||
void add_serial_task(G1AbstractSubTask* task);
|
||||
void add_parallel_task(G1AbstractSubTask* task);
|
||||
|
||||
G1BatchedGangTask(const char* name, G1GCPhaseTimes* phase_times);
|
||||
G1BatchedTask(const char* name, G1GCPhaseTimes* phase_times);
|
||||
|
||||
public:
|
||||
void work(uint worker_id) override;
|
||||
|
||||
// How many workers can this gang task keep busy and should be started for
|
||||
// How many workers can this task keep busy and should be started for
|
||||
// "optimal" performance.
|
||||
uint num_workers_estimate() const;
|
||||
// Informs the G1AbstractSubTasks about that we will start execution with the
|
||||
// given number of workers.
|
||||
void set_max_workers(uint max_workers);
|
||||
|
||||
~G1BatchedGangTask();
|
||||
~G1BatchedTask();
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1BATCHEDGANGTASK_HPP
|
||||
#endif // SHARE_GC_G1_G1BATCHEDTASK_HPP
|
@ -32,7 +32,7 @@
|
||||
#include "gc/g1/g1Allocator.inline.hpp"
|
||||
#include "gc/g1/g1Arguments.hpp"
|
||||
#include "gc/g1/g1BarrierSet.hpp"
|
||||
#include "gc/g1/g1BatchedGangTask.hpp"
|
||||
#include "gc/g1/g1BatchedTask.hpp"
|
||||
#include "gc/g1/g1CardSetFreeMemoryTask.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1CollectionSet.hpp"
|
||||
@ -138,7 +138,7 @@ void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_region
|
||||
reset_from_card_cache(start_idx, num_regions);
|
||||
}
|
||||
|
||||
void G1CollectedHeap::run_batch_task(G1BatchedGangTask* cl) {
|
||||
void G1CollectedHeap::run_batch_task(G1BatchedTask* cl) {
|
||||
uint num_workers = MAX2(1u, MIN2(cl->num_workers_estimate(), workers()->active_workers()));
|
||||
cl->set_max_workers(num_workers);
|
||||
workers()->run_task(cl, num_workers);
|
||||
@ -1273,7 +1273,7 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool G1CollectedHeap::expand(size_t expand_bytes, WorkGang* pretouch_workers, double* expand_time_ms) {
|
||||
bool G1CollectedHeap::expand(size_t expand_bytes, WorkerThreads* pretouch_workers, double* expand_time_ms) {
|
||||
size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
|
||||
aligned_expand_bytes = align_up(aligned_expand_bytes,
|
||||
HeapRegion::GrainBytes);
|
||||
@ -1682,7 +1682,7 @@ jint G1CollectedHeap::initialize() {
|
||||
_humongous_reclaim_candidates.initialize(reserved(), granularity);
|
||||
}
|
||||
|
||||
_workers = new WorkGang("GC Thread", ParallelGCThreads);
|
||||
_workers = new WorkerThreads("GC Thread", ParallelGCThreads);
|
||||
if (_workers == NULL) {
|
||||
return JNI_ENOMEM;
|
||||
}
|
||||
|
@ -64,7 +64,7 @@
|
||||
// Forward declarations
|
||||
class G1Allocator;
|
||||
class G1ArchiveAllocator;
|
||||
class G1BatchedGangTask;
|
||||
class G1BatchedTask;
|
||||
class G1CardTableEntryClosure;
|
||||
class G1ConcurrentMark;
|
||||
class G1ConcurrentMarkThread;
|
||||
@ -83,7 +83,7 @@ class MemoryPool;
|
||||
class nmethod;
|
||||
class ReferenceProcessor;
|
||||
class STWGCTimer;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
typedef OverflowTaskQueue<ScannerTask, mtGC> G1ScannerTasksQueue;
|
||||
typedef GenericTaskQueueSet<G1ScannerTasksQueue, mtGC> G1ScannerTasksQueueSet;
|
||||
@ -145,7 +145,7 @@ private:
|
||||
G1ServiceTask* _periodic_gc_task;
|
||||
G1CardSetFreeMemoryTask* _free_card_set_memory_task;
|
||||
|
||||
WorkGang* _workers;
|
||||
WorkerThreads* _workers;
|
||||
G1CardTable* _card_table;
|
||||
|
||||
Ticks _collection_pause_end;
|
||||
@ -538,10 +538,10 @@ public:
|
||||
|
||||
G1ServiceThread* service_thread() const { return _service_thread; }
|
||||
|
||||
WorkGang* workers() const { return _workers; }
|
||||
WorkerThreads* workers() const { return _workers; }
|
||||
|
||||
// Run the given batch task using the work gang.
|
||||
void run_batch_task(G1BatchedGangTask* cl);
|
||||
// Run the given batch task using the workers.
|
||||
void run_batch_task(G1BatchedTask* cl);
|
||||
|
||||
G1Allocator* allocator() {
|
||||
return _allocator;
|
||||
@ -572,7 +572,7 @@ public:
|
||||
// Returns true if the heap was expanded by the requested amount;
|
||||
// false otherwise.
|
||||
// (Rounds up to a HeapRegion boundary.)
|
||||
bool expand(size_t expand_bytes, WorkGang* pretouch_workers = NULL, double* expand_time_ms = NULL);
|
||||
bool expand(size_t expand_bytes, WorkerThreads* pretouch_workers = NULL, double* expand_time_ms = NULL);
|
||||
bool expand_single_region(uint node_index);
|
||||
|
||||
// Returns the PLAB statistics for a given destination.
|
||||
@ -1317,7 +1317,7 @@ public:
|
||||
// WhiteBox testing support.
|
||||
virtual bool supports_concurrent_gc_breakpoints() const;
|
||||
|
||||
virtual WorkGang* safepoint_workers() { return _workers; }
|
||||
virtual WorkerThreads* safepoint_workers() { return _workers; }
|
||||
|
||||
virtual bool is_archived_object(oop object) const;
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#define SHARE_GC_G1_G1COLLECTIONSETCANDIDATES_HPP
|
||||
|
||||
#include "gc/g1/g1CollectionSetCandidates.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
|
||||
|
@ -69,7 +69,7 @@ static int order_regions(HeapRegion* hr1, HeapRegion* hr2) {
|
||||
// put them into some work area unsorted. At the end the array is sorted and
|
||||
// copied into the G1CollectionSetCandidates instance; the caller will be the new
|
||||
// owner of this object.
|
||||
class G1BuildCandidateRegionsTask : public AbstractGangTask {
|
||||
class G1BuildCandidateRegionsTask : public WorkerTask {
|
||||
|
||||
// Work area for building the set of collection set candidates. Contains references
|
||||
// to heap regions with their GC efficiencies calculated. To reduce contention
|
||||
@ -223,7 +223,7 @@ class G1BuildCandidateRegionsTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
G1BuildCandidateRegionsTask(uint max_num_regions, uint chunk_size, uint num_workers) :
|
||||
AbstractGangTask("G1 Build Candidate Regions"),
|
||||
WorkerTask("G1 Build Candidate Regions"),
|
||||
_g1h(G1CollectedHeap::heap()),
|
||||
_hrclaimer(num_workers),
|
||||
_num_regions_added(0),
|
||||
@ -311,7 +311,7 @@ void G1CollectionSetChooser::prune(G1CollectionSetCandidates* candidates) {
|
||||
}
|
||||
}
|
||||
|
||||
G1CollectionSetCandidates* G1CollectionSetChooser::build(WorkGang* workers, uint max_num_regions) {
|
||||
G1CollectionSetCandidates* G1CollectionSetChooser::build(WorkerThreads* workers, uint max_num_regions) {
|
||||
uint num_workers = workers->active_workers();
|
||||
uint chunk_size = calculate_work_chunk_size(num_workers, max_num_regions);
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "runtime/globals.hpp"
|
||||
|
||||
class G1CollectionSetCandidates;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
// Helper class to calculate collection set candidates, and containing some related
|
||||
// methods.
|
||||
@ -59,7 +59,7 @@ public:
|
||||
|
||||
// Build and return set of collection set candidates sorted by decreasing gc
|
||||
// efficiency.
|
||||
static G1CollectionSetCandidates* build(WorkGang* workers, uint max_num_regions);
|
||||
static G1CollectionSetCandidates* build(WorkerThreads* workers, uint max_num_regions);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1COLLECTIONSETCHOOSER_HPP
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "gc/g1/g1BarrierSet.hpp"
|
||||
#include "gc/g1/g1BatchedGangTask.hpp"
|
||||
#include "gc/g1/g1BatchedTask.hpp"
|
||||
#include "gc/g1/g1CardSetMemory.hpp"
|
||||
#include "gc/g1/g1CollectedHeap.inline.hpp"
|
||||
#include "gc/g1/g1CollectorState.hpp"
|
||||
@ -432,7 +432,7 @@ G1ConcurrentMark::G1ConcurrentMark(G1CollectedHeap* g1h,
|
||||
_num_concurrent_workers = ConcGCThreads;
|
||||
_max_concurrent_workers = _num_concurrent_workers;
|
||||
|
||||
_concurrent_workers = new WorkGang("G1 Conc", _max_concurrent_workers);
|
||||
_concurrent_workers = new WorkerThreads("G1 Conc", _max_concurrent_workers);
|
||||
_concurrent_workers->initialize_workers();
|
||||
|
||||
if (!_global_mark_stack.initialize(MarkStackSize, MarkStackSizeMax)) {
|
||||
@ -580,7 +580,7 @@ G1ConcurrentMark::~G1ConcurrentMark() {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
class G1ClearBitMapTask : public AbstractGangTask {
|
||||
class G1ClearBitMapTask : public WorkerTask {
|
||||
public:
|
||||
static size_t chunk_size() { return M; }
|
||||
|
||||
@ -674,7 +674,7 @@ private:
|
||||
|
||||
public:
|
||||
G1ClearBitMapTask(G1ConcurrentMark* cm, uint n_workers, bool suspendible) :
|
||||
AbstractGangTask("G1 Clear Bitmap"),
|
||||
WorkerTask("G1 Clear Bitmap"),
|
||||
_cl(cm, suspendible),
|
||||
_hr_claimer(n_workers),
|
||||
_suspendible(suspendible)
|
||||
@ -690,7 +690,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void G1ConcurrentMark::clear_next_bitmap(WorkGang* workers, bool may_yield) {
|
||||
void G1ConcurrentMark::clear_next_bitmap(WorkerThreads* workers, bool may_yield) {
|
||||
assert(may_yield || SafepointSynchronize::is_at_safepoint(), "Non-yielding bitmap clear only allowed at safepoint.");
|
||||
|
||||
size_t const num_bytes_to_clear = (HeapRegion::GrainBytes * _g1h->num_regions()) / G1CMBitMap::heap_map_factor();
|
||||
@ -723,17 +723,17 @@ void G1ConcurrentMark::cleanup_for_next_mark() {
|
||||
guarantee(!_g1h->collector_state()->mark_or_rebuild_in_progress(), "invariant");
|
||||
}
|
||||
|
||||
void G1ConcurrentMark::clear_next_bitmap(WorkGang* workers) {
|
||||
void G1ConcurrentMark::clear_next_bitmap(WorkerThreads* workers) {
|
||||
assert_at_safepoint_on_vm_thread();
|
||||
// To avoid fragmentation the full collection requesting to clear the bitmap
|
||||
// might use fewer workers than available. To ensure the bitmap is cleared
|
||||
// as efficiently as possible the number of active workers are temporarily
|
||||
// increased to include all currently created workers.
|
||||
WithUpdatedActiveWorkers update(workers, workers->created_workers());
|
||||
WithActiveWorkers update(workers, workers->created_workers());
|
||||
clear_next_bitmap(workers, false);
|
||||
}
|
||||
|
||||
class G1PreConcurrentStartTask : public G1BatchedGangTask {
|
||||
class G1PreConcurrentStartTask : public G1BatchedTask {
|
||||
// Concurrent start needs claim bits to keep track of the marked-through CLDs.
|
||||
class CLDClearClaimedMarksTask;
|
||||
// Reset marking state.
|
||||
@ -805,7 +805,7 @@ void G1PreConcurrentStartTask::NoteStartOfMarkTask::set_max_workers(uint max_wor
|
||||
}
|
||||
|
||||
G1PreConcurrentStartTask::G1PreConcurrentStartTask(GCCause::Cause cause, G1ConcurrentMark* cm) :
|
||||
G1BatchedGangTask("Pre Concurrent Start", G1CollectedHeap::heap()->phase_times()) {
|
||||
G1BatchedTask("Pre Concurrent Start", G1CollectedHeap::heap()->phase_times()) {
|
||||
add_serial_task(new CLDClearClaimedMarksTask());
|
||||
add_serial_task(new ResetMarkingStateTask(cm));
|
||||
add_parallel_task(new NoteStartOfMarkTask());
|
||||
@ -889,7 +889,7 @@ void G1ConcurrentMark::enter_second_sync_barrier(uint worker_id) {
|
||||
// at this point everything should be re-initialized and ready to go
|
||||
}
|
||||
|
||||
class G1CMConcurrentMarkingTask : public AbstractGangTask {
|
||||
class G1CMConcurrentMarkingTask : public WorkerTask {
|
||||
G1ConcurrentMark* _cm;
|
||||
|
||||
public:
|
||||
@ -923,7 +923,7 @@ public:
|
||||
}
|
||||
|
||||
G1CMConcurrentMarkingTask(G1ConcurrentMark* cm) :
|
||||
AbstractGangTask("Concurrent Mark"), _cm(cm) { }
|
||||
WorkerTask("Concurrent Mark"), _cm(cm) { }
|
||||
|
||||
~G1CMConcurrentMarkingTask() { }
|
||||
};
|
||||
@ -971,11 +971,11 @@ void G1ConcurrentMark::scan_root_region(const MemRegion* region, uint worker_id)
|
||||
}
|
||||
}
|
||||
|
||||
class G1CMRootRegionScanTask : public AbstractGangTask {
|
||||
class G1CMRootRegionScanTask : public WorkerTask {
|
||||
G1ConcurrentMark* _cm;
|
||||
public:
|
||||
G1CMRootRegionScanTask(G1ConcurrentMark* cm) :
|
||||
AbstractGangTask("G1 Root Region Scan"), _cm(cm) { }
|
||||
WorkerTask("G1 Root Region Scan"), _cm(cm) { }
|
||||
|
||||
void work(uint worker_id) {
|
||||
G1CMRootMemRegions* root_regions = _cm->root_regions();
|
||||
@ -1046,8 +1046,8 @@ void G1ConcurrentMark::mark_from_roots() {
|
||||
// Setting active workers is not guaranteed since fewer
|
||||
// worker threads may currently exist and more may not be
|
||||
// available.
|
||||
active_workers = _concurrent_workers->update_active_workers(active_workers);
|
||||
log_info(gc, task)("Using %u workers of %u for marking", active_workers, _concurrent_workers->total_workers());
|
||||
active_workers = _concurrent_workers->set_active_workers(active_workers);
|
||||
log_info(gc, task)("Using %u workers of %u for marking", active_workers, _concurrent_workers->max_workers());
|
||||
|
||||
// Parallel task terminator is set in "set_concurrency_and_phase()"
|
||||
set_concurrency_and_phase(active_workers, true /* concurrent */);
|
||||
@ -1075,7 +1075,7 @@ void G1ConcurrentMark::verify_during_pause(G1HeapVerifier::G1VerifyType type, Ve
|
||||
verifier->check_bitmaps(caller);
|
||||
}
|
||||
|
||||
class G1UpdateRemSetTrackingBeforeRebuildTask : public AbstractGangTask {
|
||||
class G1UpdateRemSetTrackingBeforeRebuildTask : public WorkerTask {
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ConcurrentMark* _cm;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
@ -1176,7 +1176,7 @@ class G1UpdateRemSetTrackingBeforeRebuildTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
G1UpdateRemSetTrackingBeforeRebuildTask(G1CollectedHeap* g1h, G1ConcurrentMark* cm, uint num_workers) :
|
||||
AbstractGangTask("G1 Update RemSet Tracking Before Rebuild"),
|
||||
WorkerTask("G1 Update RemSet Tracking Before Rebuild"),
|
||||
_g1h(g1h), _cm(cm), _hrclaimer(num_workers), _total_selected_for_rebuild(0), _cl("Post-Marking") { }
|
||||
|
||||
virtual void work(uint worker_id) {
|
||||
@ -1307,7 +1307,7 @@ void G1ConcurrentMark::remark() {
|
||||
policy->record_concurrent_mark_remark_end();
|
||||
}
|
||||
|
||||
class G1ReclaimEmptyRegionsTask : public AbstractGangTask {
|
||||
class G1ReclaimEmptyRegionsTask : public WorkerTask {
|
||||
// Per-region work during the Cleanup pause.
|
||||
class G1ReclaimEmptyRegionsClosure : public HeapRegionClosure {
|
||||
G1CollectedHeap* _g1h;
|
||||
@ -1362,7 +1362,7 @@ class G1ReclaimEmptyRegionsTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
G1ReclaimEmptyRegionsTask(G1CollectedHeap* g1h, FreeRegionList* cleanup_list, uint n_workers) :
|
||||
AbstractGangTask("G1 Cleanup"),
|
||||
WorkerTask("G1 Cleanup"),
|
||||
_g1h(g1h),
|
||||
_cleanup_list(cleanup_list),
|
||||
_hrclaimer(n_workers) {
|
||||
@ -1389,7 +1389,7 @@ public:
|
||||
};
|
||||
|
||||
void G1ConcurrentMark::reclaim_empty_regions() {
|
||||
WorkGang* workers = _g1h->workers();
|
||||
WorkerThreads* workers = _g1h->workers();
|
||||
FreeRegionList empty_regions_list("Empty Regions After Mark List");
|
||||
|
||||
G1ReclaimEmptyRegionsTask cl(_g1h, &empty_regions_list, workers->active_workers());
|
||||
@ -1613,7 +1613,7 @@ void G1ConcurrentMark::weak_refs_work() {
|
||||
|
||||
// We need at least one active thread. If reference processing
|
||||
// is not multi-threaded we use the current (VMThread) thread,
|
||||
// otherwise we use the work gang from the G1CollectedHeap and
|
||||
// otherwise we use the workers from the G1CollectedHeap and
|
||||
// we utilize all the worker threads we can.
|
||||
uint active_workers = (ParallelRefProcEnabled ? _g1h->workers()->active_workers() : 1U);
|
||||
active_workers = clamp(active_workers, 1u, _max_num_tasks);
|
||||
@ -1802,7 +1802,7 @@ class G1RemarkThreadsClosure : public ThreadClosure {
|
||||
}
|
||||
};
|
||||
|
||||
class G1CMRemarkTask : public AbstractGangTask {
|
||||
class G1CMRemarkTask : public WorkerTask {
|
||||
G1ConcurrentMark* _cm;
|
||||
public:
|
||||
void work(uint worker_id) {
|
||||
@ -1826,7 +1826,7 @@ public:
|
||||
}
|
||||
|
||||
G1CMRemarkTask(G1ConcurrentMark* cm, uint active_workers) :
|
||||
AbstractGangTask("Par Remark"), _cm(cm) {
|
||||
WorkerTask("Par Remark"), _cm(cm) {
|
||||
_cm->terminator()->reset_for_reuse(active_workers);
|
||||
}
|
||||
};
|
||||
@ -1842,7 +1842,7 @@ void G1ConcurrentMark::finalize_marking() {
|
||||
// Leave _parallel_marking_threads at it's
|
||||
// value originally calculated in the G1ConcurrentMark
|
||||
// constructor and pass values of the active workers
|
||||
// through the gang in the task.
|
||||
// through the task.
|
||||
|
||||
{
|
||||
StrongRootsScope srs(active_workers);
|
||||
@ -2561,7 +2561,7 @@ bool G1ConcurrentMark::try_stealing(uint worker_id, G1TaskQueueEntry& task_entry
|
||||
processing closures.
|
||||
|
||||
The value of is_serial must be false when do_marking_step is
|
||||
being called by any of the worker threads in a work gang.
|
||||
being called by any of the worker threads.
|
||||
Examples include the concurrent marking code (CMMarkingTask),
|
||||
the MT remark code, and the MT reference processing closures.
|
||||
|
||||
|
@ -34,7 +34,8 @@
|
||||
#include "gc/shared/taskTerminator.hpp"
|
||||
#include "gc/shared/taskqueue.hpp"
|
||||
#include "gc/shared/verifyOption.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shared/workerUtils.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/compilerWarnings.hpp"
|
||||
#include "utilities/numberSeq.hpp"
|
||||
@ -325,8 +326,8 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
|
||||
// ensure, that no task starts doing work before all data
|
||||
// structures (local and global) have been re-initialized. When they
|
||||
// exit it, they are free to start working again.
|
||||
WorkGangBarrierSync _first_overflow_barrier_sync;
|
||||
WorkGangBarrierSync _second_overflow_barrier_sync;
|
||||
WorkerThreadsBarrierSync _first_overflow_barrier_sync;
|
||||
WorkerThreadsBarrierSync _second_overflow_barrier_sync;
|
||||
|
||||
// This is set by any task, when an overflow on the global data
|
||||
// structures is detected
|
||||
@ -354,7 +355,7 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
|
||||
|
||||
double* _accum_task_vtime; // Accumulated task vtime
|
||||
|
||||
WorkGang* _concurrent_workers;
|
||||
WorkerThreads* _concurrent_workers;
|
||||
uint _num_concurrent_workers; // The number of marking worker threads we're using
|
||||
uint _max_concurrent_workers; // Maximum number of marking worker threads
|
||||
|
||||
@ -440,9 +441,9 @@ class G1ConcurrentMark : public CHeapObj<mtGC> {
|
||||
void enter_first_sync_barrier(uint worker_id);
|
||||
void enter_second_sync_barrier(uint worker_id);
|
||||
|
||||
// Clear the next marking bitmap in parallel using the given WorkGang. If may_yield is
|
||||
// Clear the next marking bitmap in parallel using the given WorkerThreads. If may_yield is
|
||||
// true, periodically insert checks to see if this method should exit prematurely.
|
||||
void clear_next_bitmap(WorkGang* workers, bool may_yield);
|
||||
void clear_next_bitmap(WorkerThreads* workers, bool may_yield);
|
||||
|
||||
// Region statistics gathered during marking.
|
||||
G1RegionMarkStats* _region_mark_stats;
|
||||
@ -534,7 +535,7 @@ public:
|
||||
void cleanup_for_next_mark();
|
||||
|
||||
// Clear the next marking bitmap during safepoint.
|
||||
void clear_next_bitmap(WorkGang* workers);
|
||||
void clear_next_bitmap(WorkerThreads* workers);
|
||||
|
||||
// These two methods do the work that needs to be done at the start and end of the
|
||||
// concurrent start pause.
|
||||
|
@ -201,7 +201,7 @@ public:
|
||||
};
|
||||
|
||||
G1ParRemoveSelfForwardPtrsTask::G1ParRemoveSelfForwardPtrsTask(G1EvacFailureRegions* evac_failure_regions) :
|
||||
AbstractGangTask("G1 Remove Self-forwarding Pointers"),
|
||||
WorkerTask("G1 Remove Self-forwarding Pointers"),
|
||||
_g1h(G1CollectedHeap::heap()),
|
||||
_hrclaimer(_g1h->workers()->active_workers()),
|
||||
_evac_failure_regions(evac_failure_regions),
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "gc/g1/g1OopClosures.hpp"
|
||||
#include "gc/g1/heapRegionManager.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
class G1CollectedHeap;
|
||||
@ -35,7 +35,7 @@ class G1EvacFailureRegions;
|
||||
|
||||
// Task to fixup self-forwarding pointers
|
||||
// installed as a result of an evacuation failure.
|
||||
class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask {
|
||||
class G1ParRemoveSelfForwardPtrsTask: public WorkerTask {
|
||||
protected:
|
||||
G1CollectedHeap* _g1h;
|
||||
HeapRegionClaimer _hrclaimer;
|
||||
|
@ -75,7 +75,7 @@ ReferenceProcessor* G1FullCollector::reference_processor() {
|
||||
|
||||
uint G1FullCollector::calc_active_workers() {
|
||||
G1CollectedHeap* heap = G1CollectedHeap::heap();
|
||||
uint max_worker_count = heap->workers()->total_workers();
|
||||
uint max_worker_count = heap->workers()->max_workers();
|
||||
// Only calculate number of workers if UseDynamicNumberOfGCThreads
|
||||
// is enabled, otherwise use max.
|
||||
if (!UseDynamicNumberOfGCThreads) {
|
||||
@ -102,7 +102,7 @@ uint G1FullCollector::calc_active_workers() {
|
||||
log_debug(gc, task)("Requesting %u active workers for full compaction (waste limited workers: %u, "
|
||||
"adaptive workers: %u, used limited workers: %u)",
|
||||
worker_count, heap_waste_worker_limit, active_worker_limit, used_worker_limit);
|
||||
worker_count = heap->workers()->update_active_workers(worker_count);
|
||||
worker_count = heap->workers()->set_active_workers(worker_count);
|
||||
log_info(gc, task)("Using %u workers of %u for full compaction", worker_count, max_worker_count);
|
||||
|
||||
return worker_count;
|
||||
@ -332,7 +332,7 @@ void G1FullCollector::restore_marks() {
|
||||
_preserved_marks_set.reclaim();
|
||||
}
|
||||
|
||||
void G1FullCollector::run_task(AbstractGangTask* task) {
|
||||
void G1FullCollector::run_task(WorkerTask* task) {
|
||||
_heap->workers()->run_task(task, _num_workers);
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/oopsHierarchy.hpp"
|
||||
|
||||
class AbstractGangTask;
|
||||
class WorkerTask;
|
||||
class G1CMBitMap;
|
||||
class G1FullGCMarker;
|
||||
class G1FullGCScope;
|
||||
@ -134,7 +134,7 @@ private:
|
||||
void restore_marks();
|
||||
void verify_after_marking();
|
||||
|
||||
void run_task(AbstractGangTask* task);
|
||||
void run_task(WorkerTask* task);
|
||||
};
|
||||
|
||||
|
||||
|
@ -25,17 +25,17 @@
|
||||
#ifndef SHARE_GC_G1_G1FULLGCTASK_HPP
|
||||
#define SHARE_GC_G1_G1FULLGCTASK_HPP
|
||||
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
|
||||
class G1FullCollector;
|
||||
|
||||
class G1FullGCTask : public AbstractGangTask {
|
||||
class G1FullGCTask : public WorkerTask {
|
||||
G1FullCollector* _collector;
|
||||
|
||||
protected:
|
||||
G1FullGCTask(const char* name, G1FullCollector* collector) :
|
||||
AbstractGangTask(name),
|
||||
WorkerTask(name),
|
||||
_collector(collector) { }
|
||||
|
||||
G1FullCollector* collector() { return _collector; }
|
||||
|
@ -426,7 +426,7 @@ public:
|
||||
|
||||
// This is the task used for parallel verification of the heap regions
|
||||
|
||||
class G1ParVerifyTask: public AbstractGangTask {
|
||||
class G1ParVerifyTask: public WorkerTask {
|
||||
private:
|
||||
G1CollectedHeap* _g1h;
|
||||
VerifyOption _vo;
|
||||
@ -438,7 +438,7 @@ public:
|
||||
// _vo == UseNextMarking -> use "next" marking information,
|
||||
// _vo == UseFullMarking -> use "next" marking bitmap but no TAMS
|
||||
G1ParVerifyTask(G1CollectedHeap* g1h, VerifyOption vo) :
|
||||
AbstractGangTask("Parallel verify task"),
|
||||
WorkerTask("Parallel verify task"),
|
||||
_g1h(g1h),
|
||||
_vo(vo),
|
||||
_failures(false),
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/g1PageBasedVirtualSpace.hpp"
|
||||
#include "gc/shared/pretouchTask.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "oops/markWord.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
@ -233,10 +233,10 @@ void G1PageBasedVirtualSpace::uncommit(size_t start_page, size_t size_in_pages)
|
||||
_committed.par_clear_range(start_page, end_page, BitMap::unknown_range);
|
||||
}
|
||||
|
||||
void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang) {
|
||||
void G1PageBasedVirtualSpace::pretouch(size_t start_page, size_t size_in_pages, WorkerThreads* pretouch_workers) {
|
||||
|
||||
PretouchTask::pretouch("G1 PreTouch", page_start(start_page), bounded_end_addr(start_page + size_in_pages),
|
||||
_page_size, pretouch_gang);
|
||||
_page_size, pretouch_workers);
|
||||
}
|
||||
|
||||
bool G1PageBasedVirtualSpace::contains(const void* p) const {
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "utilities/align.hpp"
|
||||
#include "utilities/bitMap.hpp"
|
||||
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
// Virtual space management helper for a virtual space with an OS page allocation
|
||||
// granularity.
|
||||
@ -117,7 +117,7 @@ class G1PageBasedVirtualSpace {
|
||||
// Uncommit the given area of pages starting at start being size_in_pages large.
|
||||
void uncommit(size_t start_page, size_t size_in_pages);
|
||||
|
||||
void pretouch(size_t start_page, size_t size_in_pages, WorkGang* pretouch_gang = NULL);
|
||||
void pretouch(size_t start_page, size_t size_in_pages, WorkerThreads* pretouch_workers = NULL);
|
||||
|
||||
// Initialize the given reserved space with the given base address and the size
|
||||
// actually used.
|
||||
|
@ -54,7 +54,7 @@ void JVMCICleaningTask::work(bool unloading_occurred) {
|
||||
G1ParallelCleaningTask::G1ParallelCleaningTask(BoolObjectClosure* is_alive,
|
||||
uint num_workers,
|
||||
bool unloading_occurred) :
|
||||
AbstractGangTask("G1 Parallel Cleaning"),
|
||||
WorkerTask("G1 Parallel Cleaning"),
|
||||
_unloading_occurred(unloading_occurred),
|
||||
_code_cache_task(num_workers, is_alive, unloading_occurred),
|
||||
JVMCI_ONLY(_jvmci_cleaning_task() COMMA)
|
||||
|
@ -43,7 +43,7 @@ private:
|
||||
|
||||
// Do cleanup of some weakly held data in the same parallel task.
|
||||
// Assumes a non-moving context.
|
||||
class G1ParallelCleaningTask : public AbstractGangTask {
|
||||
class G1ParallelCleaningTask : public WorkerTask {
|
||||
private:
|
||||
bool _unloading_occurred;
|
||||
CodeCacheUnloadingTask _code_cache_task;
|
||||
|
@ -89,7 +89,7 @@ class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
|
||||
return _region_commit_map.get_next_one_offset(start_idx, end) == end;
|
||||
}
|
||||
|
||||
virtual void commit_regions(uint start_idx, size_t num_regions, WorkGang* pretouch_gang) {
|
||||
virtual void commit_regions(uint start_idx, size_t num_regions, WorkerThreads* pretouch_workers) {
|
||||
guarantee(is_range_uncommitted(start_idx, num_regions),
|
||||
"Range not uncommitted, start: %u, num_regions: " SIZE_FORMAT,
|
||||
start_idx, num_regions);
|
||||
@ -105,7 +105,7 @@ class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
|
||||
}
|
||||
}
|
||||
if (AlwaysPreTouch) {
|
||||
_storage.pretouch(start_page, size_in_pages, pretouch_gang);
|
||||
_storage.pretouch(start_page, size_in_pages, pretouch_workers);
|
||||
}
|
||||
_region_commit_map.par_set_range(start_idx, start_idx + num_regions, BitMap::unknown_range);
|
||||
fire_on_commit(start_idx, num_regions, zero_filled);
|
||||
@ -172,7 +172,7 @@ class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
|
||||
guarantee((page_size * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity");
|
||||
}
|
||||
|
||||
virtual void commit_regions(uint start_idx, size_t num_regions, WorkGang* pretouch_gang) {
|
||||
virtual void commit_regions(uint start_idx, size_t num_regions, WorkerThreads* pretouch_workers) {
|
||||
uint region_limit = (uint)(start_idx + num_regions);
|
||||
assert(num_regions > 0, "Must commit at least one region");
|
||||
assert(_region_commit_map.get_next_one_offset(start_idx, region_limit) == region_limit,
|
||||
@ -219,7 +219,7 @@ class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
|
||||
}
|
||||
|
||||
if (AlwaysPreTouch && num_committed > 0) {
|
||||
_storage.pretouch(first_committed, num_committed, pretouch_gang);
|
||||
_storage.pretouch(first_committed, num_committed, pretouch_workers);
|
||||
}
|
||||
|
||||
fire_on_commit(start_idx, num_regions, all_zero_filled);
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "memory/allocation.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
class G1MappingChangedListener {
|
||||
public:
|
||||
@ -70,7 +70,7 @@ class G1RegionToSpaceMapper : public CHeapObj<mtGC> {
|
||||
|
||||
virtual ~G1RegionToSpaceMapper() {}
|
||||
|
||||
virtual void commit_regions(uint start_idx, size_t num_regions = 1, WorkGang* pretouch_workers = NULL) = 0;
|
||||
virtual void commit_regions(uint start_idx, size_t num_regions = 1, WorkerThreads* pretouch_workers = NULL) = 0;
|
||||
virtual void uncommit_regions(uint start_idx, size_t num_regions = 1) = 0;
|
||||
|
||||
// Creates an appropriate G1RegionToSpaceMapper for the given parameters.
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/g1/g1BarrierSet.hpp"
|
||||
#include "gc/g1/g1BatchedGangTask.hpp"
|
||||
#include "gc/g1/g1BatchedTask.hpp"
|
||||
#include "gc/g1/g1BlockOffsetTable.inline.hpp"
|
||||
#include "gc/g1/g1CardSet.inline.hpp"
|
||||
#include "gc/g1/g1CardTable.inline.hpp"
|
||||
@ -406,7 +406,7 @@ public:
|
||||
|
||||
G1CollectedHeap* g1h = G1CollectedHeap::heap();
|
||||
|
||||
WorkGang* workers = g1h->workers();
|
||||
WorkerThreads* workers = g1h->workers();
|
||||
uint const max_workers = workers->active_workers();
|
||||
|
||||
uint const start_pos = num_regions * worker_id / max_workers;
|
||||
@ -1102,7 +1102,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class G1MergeHeapRootsTask : public AbstractGangTask {
|
||||
class G1MergeHeapRootsTask : public WorkerTask {
|
||||
|
||||
class G1MergeCardSetStats {
|
||||
size_t _merged[G1GCPhaseTimes::MergeRSContainersSentinel];
|
||||
@ -1371,7 +1371,7 @@ class G1MergeHeapRootsTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
G1MergeHeapRootsTask(G1RemSetScanState* scan_state, uint num_workers, bool initial_evacuation) :
|
||||
AbstractGangTask("G1 Merge Heap Roots"),
|
||||
WorkerTask("G1 Merge Heap Roots"),
|
||||
_hr_claimer(num_workers),
|
||||
_scan_state(scan_state),
|
||||
_dirty_card_buffers(),
|
||||
@ -1490,7 +1490,7 @@ void G1RemSet::merge_heap_roots(bool initial_evacuation) {
|
||||
}
|
||||
}
|
||||
|
||||
WorkGang* workers = g1h->workers();
|
||||
WorkerThreads* workers = g1h->workers();
|
||||
size_t const increment_length = g1h->collection_set()->increment_length();
|
||||
|
||||
uint const num_workers = initial_evacuation ? workers->active_workers() :
|
||||
@ -1738,7 +1738,7 @@ void G1RemSet::print_summary_info() {
|
||||
}
|
||||
}
|
||||
|
||||
class G1RebuildRemSetTask: public AbstractGangTask {
|
||||
class G1RebuildRemSetTask: public WorkerTask {
|
||||
// Aggregate the counting data that was constructed concurrently
|
||||
// with marking.
|
||||
class G1RebuildRemSetHeapRegionClosure : public HeapRegionClosure {
|
||||
@ -1974,7 +1974,7 @@ public:
|
||||
G1RebuildRemSetTask(G1ConcurrentMark* cm,
|
||||
uint n_workers,
|
||||
uint worker_id_offset) :
|
||||
AbstractGangTask("G1 Rebuild Remembered Set"),
|
||||
WorkerTask("G1 Rebuild Remembered Set"),
|
||||
_hr_claimer(n_workers),
|
||||
_cm(cm),
|
||||
_worker_id_offset(worker_id_offset) {
|
||||
@ -1991,7 +1991,7 @@ public:
|
||||
};
|
||||
|
||||
void G1RemSet::rebuild_rem_set(G1ConcurrentMark* cm,
|
||||
WorkGang* workers,
|
||||
WorkerThreads* workers,
|
||||
uint worker_id_offset) {
|
||||
uint num_workers = workers->active_workers();
|
||||
|
||||
|
@ -113,7 +113,7 @@ public:
|
||||
|
||||
// Print coarsening stats.
|
||||
void print_coarsen_stats();
|
||||
// Creates a gang task for cleaining up temporary data structures and the
|
||||
// Creates a task for cleaining up temporary data structures and the
|
||||
// card table, removing temporary duplicate detection information.
|
||||
G1AbstractSubTask* create_cleanup_after_scan_heap_roots_task();
|
||||
// Excludes the given region from heap root scanning.
|
||||
@ -149,8 +149,8 @@ public:
|
||||
void print_periodic_summary_info(const char* header, uint period_count);
|
||||
|
||||
// Rebuilds the remembered set by scanning from bottom to TARS for all regions
|
||||
// using the given work gang.
|
||||
void rebuild_rem_set(G1ConcurrentMark* cm, WorkGang* workers, uint worker_id_offset);
|
||||
// using the given workers.
|
||||
void rebuild_rem_set(G1ConcurrentMark* cm, WorkerThreads* workers, uint worker_id_offset);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_G1_G1REMSET_HPP
|
||||
|
@ -54,7 +54,7 @@
|
||||
#include "gc/shared/referenceProcessor.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "gc/shared/workerPolicy.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "utilities/ticks.hpp"
|
||||
@ -270,7 +270,7 @@ ReferenceProcessor* G1YoungCollector::ref_processor_stw() const {
|
||||
return _g1h->ref_processor_stw();
|
||||
}
|
||||
|
||||
WorkGang* G1YoungCollector::workers() const {
|
||||
WorkerThreads* G1YoungCollector::workers() const {
|
||||
return _g1h->workers();
|
||||
}
|
||||
|
||||
@ -323,7 +323,7 @@ void G1YoungCollector::calculate_collection_set(G1EvacInfo* evacuation_info, dou
|
||||
}
|
||||
}
|
||||
|
||||
class G1PrepareEvacuationTask : public AbstractGangTask {
|
||||
class G1PrepareEvacuationTask : public WorkerTask {
|
||||
class G1PrepareRegionsClosure : public HeapRegionClosure {
|
||||
G1CollectedHeap* _g1h;
|
||||
G1PrepareEvacuationTask* _parent_task;
|
||||
@ -460,7 +460,7 @@ class G1PrepareEvacuationTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
G1PrepareEvacuationTask(G1CollectedHeap* g1h) :
|
||||
AbstractGangTask("Prepare Evacuation"),
|
||||
WorkerTask("Prepare Evacuation"),
|
||||
_g1h(g1h),
|
||||
_claimer(_g1h->workers()->active_workers()),
|
||||
_humongous_total(0),
|
||||
@ -495,18 +495,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
Tickspan G1YoungCollector::run_task_timed(AbstractGangTask* task) {
|
||||
Tickspan G1YoungCollector::run_task_timed(WorkerTask* task) {
|
||||
Ticks start = Ticks::now();
|
||||
workers()->run_task(task);
|
||||
return Ticks::now() - start;
|
||||
}
|
||||
|
||||
void G1YoungCollector::set_young_collection_default_active_worker_threads(){
|
||||
uint active_workers = WorkerPolicy::calc_active_workers(workers()->total_workers(),
|
||||
uint active_workers = WorkerPolicy::calc_active_workers(workers()->max_workers(),
|
||||
workers()->active_workers(),
|
||||
Threads::number_of_non_daemon_threads());
|
||||
active_workers = workers()->update_active_workers(active_workers);
|
||||
log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers()->total_workers());
|
||||
active_workers = workers()->set_active_workers(active_workers);
|
||||
log_info(gc,task)("Using %u workers of %u for evacuation", active_workers, workers()->max_workers());
|
||||
}
|
||||
|
||||
void G1YoungCollector::pre_evacuate_collection_set(G1EvacInfo* evacuation_info, G1ParScanThreadStateSet* per_thread_states) {
|
||||
@ -625,7 +625,7 @@ public:
|
||||
size_t term_attempts() const { return _term_attempts; }
|
||||
};
|
||||
|
||||
class G1EvacuateRegionsBaseTask : public AbstractGangTask {
|
||||
class G1EvacuateRegionsBaseTask : public WorkerTask {
|
||||
protected:
|
||||
G1CollectedHeap* _g1h;
|
||||
G1ParScanThreadStateSet* _per_thread_states;
|
||||
@ -673,7 +673,7 @@ public:
|
||||
G1ParScanThreadStateSet* per_thread_states,
|
||||
G1ScannerTasksQueueSet* task_queues,
|
||||
uint num_workers) :
|
||||
AbstractGangTask(name),
|
||||
WorkerTask(name),
|
||||
_g1h(G1CollectedHeap::heap()),
|
||||
_per_thread_states(per_thread_states),
|
||||
_task_queues(task_queues),
|
||||
@ -757,7 +757,7 @@ void G1YoungCollector::evacuate_initial_collection_set(G1ParScanThreadStateSet*
|
||||
has_optional_evacuation_work);
|
||||
task_time = run_task_timed(&g1_par_task);
|
||||
// Closing the inner scope will execute the destructor for the
|
||||
// G1RootProcessor object. By subtracting the WorkGang task from the total
|
||||
// G1RootProcessor object. By subtracting the WorkerThreads task from the total
|
||||
// time of this scope, we get the "NMethod List Cleanup" time. This list is
|
||||
// constructed during "STW two-phase nmethod root processing", see more in
|
||||
// nmethod.hpp
|
||||
@ -1104,12 +1104,12 @@ void G1YoungCollector::collect() {
|
||||
// Young GC internal pause timing
|
||||
G1YoungGCNotifyPauseMark npm(this);
|
||||
|
||||
// Verification may use the gang workers, so they must be set up before.
|
||||
// Verification may use the workers, so they must be set up before.
|
||||
// Individual parallel phases may override this.
|
||||
set_young_collection_default_active_worker_threads();
|
||||
|
||||
// Wait for root region scan here to make sure that it is done before any
|
||||
// use of the STW work gang to maximize cpu use (i.e. all cores are available
|
||||
// use of the STW workers to maximize cpu use (i.e. all cores are available
|
||||
// just to do that).
|
||||
wait_for_root_region_scanning();
|
||||
|
||||
|
@ -30,9 +30,9 @@
|
||||
#include "gc/shared/gcCause.hpp"
|
||||
#include "gc/shared/taskqueue.hpp"
|
||||
|
||||
class AbstractGangTask;
|
||||
class WorkerTask;
|
||||
class G1Allocator;
|
||||
class G1BatchedGangTask;
|
||||
class G1BatchedTask;
|
||||
class G1CardSetMemoryStats;
|
||||
class G1CollectedHeap;
|
||||
class G1CollectionSet;
|
||||
@ -52,7 +52,7 @@ class G1RemSet;
|
||||
class G1SurvivorRegions;
|
||||
class G1YoungGCEvacFailureInjector;
|
||||
class STWGCTimer;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
class outputStream;
|
||||
|
||||
@ -78,7 +78,7 @@ class G1YoungCollector {
|
||||
G1ScannerTasksQueueSet* task_queues() const;
|
||||
G1SurvivorRegions* survivor_regions() const;
|
||||
ReferenceProcessor* ref_processor_stw() const;
|
||||
WorkGang* workers() const;
|
||||
WorkerThreads* workers() const;
|
||||
G1YoungGCEvacFailureInjector* evac_failure_injector() const;
|
||||
|
||||
GCCause::Cause _gc_cause;
|
||||
@ -89,9 +89,9 @@ class G1YoungCollector {
|
||||
// Evacuation failure tracking.
|
||||
G1EvacFailureRegions _evac_failure_regions;
|
||||
|
||||
// Runs the given AbstractGangTask with the current active workers,
|
||||
// Runs the given WorkerTask with the current active workers,
|
||||
// returning the total time taken.
|
||||
Tickspan run_task_timed(AbstractGangTask* task);
|
||||
Tickspan run_task_timed(WorkerTask* task);
|
||||
|
||||
void wait_for_root_region_scanning();
|
||||
|
||||
|
@ -125,7 +125,7 @@ public:
|
||||
|
||||
G1PostEvacuateCollectionSetCleanupTask1::G1PostEvacuateCollectionSetCleanupTask1(G1ParScanThreadStateSet* per_thread_states,
|
||||
G1EvacFailureRegions* evac_failure_regions) :
|
||||
G1BatchedGangTask("Post Evacuate Cleanup 1", G1CollectedHeap::heap()->phase_times())
|
||||
G1BatchedTask("Post Evacuate Cleanup 1", G1CollectedHeap::heap()->phase_times())
|
||||
{
|
||||
bool evacuation_failed = evac_failure_regions->evacuation_failed();
|
||||
|
||||
@ -306,7 +306,7 @@ public:
|
||||
|
||||
class G1PostEvacuateCollectionSetCleanupTask2::RestorePreservedMarksTask : public G1AbstractSubTask {
|
||||
PreservedMarksSet* _preserved_marks;
|
||||
AbstractGangTask* _task;
|
||||
WorkerTask* _task;
|
||||
|
||||
public:
|
||||
RestorePreservedMarksTask(PreservedMarksSet* preserved_marks) :
|
||||
@ -672,7 +672,7 @@ public:
|
||||
G1PostEvacuateCollectionSetCleanupTask2::G1PostEvacuateCollectionSetCleanupTask2(G1ParScanThreadStateSet* per_thread_states,
|
||||
G1EvacInfo* evacuation_info,
|
||||
G1EvacFailureRegions* evac_failure_regions) :
|
||||
G1BatchedGangTask("Post Evacuate Cleanup 2", G1CollectedHeap::heap()->phase_times())
|
||||
G1BatchedTask("Post Evacuate Cleanup 2", G1CollectedHeap::heap()->phase_times())
|
||||
{
|
||||
add_serial_task(new ResetHotCardCacheTask());
|
||||
add_serial_task(new PurgeCodeRootsTask());
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef SHARE_GC_G1_G1YOUNGGCPOSTEVACUATETASKS_HPP
|
||||
#define SHARE_GC_G1_G1YOUNGGCPOSTEVACUATETASKS_HPP
|
||||
|
||||
#include "gc/g1/g1BatchedGangTask.hpp"
|
||||
#include "gc/g1/g1BatchedTask.hpp"
|
||||
#include "gc/g1/g1EvacFailure.hpp"
|
||||
|
||||
class FreeCSetStats;
|
||||
@ -41,7 +41,7 @@ class G1ParScanThreadStateSet;
|
||||
// - Sample Collection Set Candidates (s)
|
||||
// - Remove Self Forwards (on evacuation failure)
|
||||
// - Clear Card Table
|
||||
class G1PostEvacuateCollectionSetCleanupTask1 : public G1BatchedGangTask {
|
||||
class G1PostEvacuateCollectionSetCleanupTask1 : public G1BatchedTask {
|
||||
class MergePssTask;
|
||||
class RecalculateUsedTask;
|
||||
class SampleCollectionSetCandidatesTask;
|
||||
@ -60,7 +60,7 @@ public:
|
||||
// - Redirty Logged Cards
|
||||
// - Restore Preserved Marks (on evacuation failure)
|
||||
// - Free Collection Set
|
||||
class G1PostEvacuateCollectionSetCleanupTask2 : public G1BatchedGangTask {
|
||||
class G1PostEvacuateCollectionSetCleanupTask2 : public G1BatchedTask {
|
||||
class EagerlyReclaimHumongousObjectsTask;
|
||||
class PurgeCodeRootsTask;
|
||||
class ResetHotCardCacheTask;
|
||||
|
@ -166,8 +166,8 @@ HeapRegion* HeapRegionManager::new_heap_region(uint hrm_index) {
|
||||
return g1h->new_heap_region(hrm_index, mr);
|
||||
}
|
||||
|
||||
void HeapRegionManager::expand(uint start, uint num_regions, WorkGang* pretouch_gang) {
|
||||
commit_regions(start, num_regions, pretouch_gang);
|
||||
void HeapRegionManager::expand(uint start, uint num_regions, WorkerThreads* pretouch_workers) {
|
||||
commit_regions(start, num_regions, pretouch_workers);
|
||||
for (uint i = start; i < start + num_regions; i++) {
|
||||
HeapRegion* hr = _regions.get_by_index(i);
|
||||
if (hr == NULL) {
|
||||
@ -181,21 +181,21 @@ void HeapRegionManager::expand(uint start, uint num_regions, WorkGang* pretouch_
|
||||
activate_regions(start, num_regions);
|
||||
}
|
||||
|
||||
void HeapRegionManager::commit_regions(uint index, size_t num_regions, WorkGang* pretouch_gang) {
|
||||
void HeapRegionManager::commit_regions(uint index, size_t num_regions, WorkerThreads* pretouch_workers) {
|
||||
guarantee(num_regions > 0, "Must commit more than zero regions");
|
||||
guarantee(num_regions <= available(),
|
||||
"Cannot commit more than the maximum amount of regions");
|
||||
|
||||
_heap_mapper->commit_regions(index, num_regions, pretouch_gang);
|
||||
_heap_mapper->commit_regions(index, num_regions, pretouch_workers);
|
||||
|
||||
// Also commit auxiliary data
|
||||
_prev_bitmap_mapper->commit_regions(index, num_regions, pretouch_gang);
|
||||
_next_bitmap_mapper->commit_regions(index, num_regions, pretouch_gang);
|
||||
_prev_bitmap_mapper->commit_regions(index, num_regions, pretouch_workers);
|
||||
_next_bitmap_mapper->commit_regions(index, num_regions, pretouch_workers);
|
||||
|
||||
_bot_mapper->commit_regions(index, num_regions, pretouch_gang);
|
||||
_cardtable_mapper->commit_regions(index, num_regions, pretouch_gang);
|
||||
_bot_mapper->commit_regions(index, num_regions, pretouch_workers);
|
||||
_cardtable_mapper->commit_regions(index, num_regions, pretouch_workers);
|
||||
|
||||
_card_counts_mapper->commit_regions(index, num_regions, pretouch_gang);
|
||||
_card_counts_mapper->commit_regions(index, num_regions, pretouch_workers);
|
||||
}
|
||||
|
||||
void HeapRegionManager::uncommit_regions(uint start, uint num_regions) {
|
||||
@ -346,7 +346,7 @@ uint HeapRegionManager::expand_inactive(uint num_regions) {
|
||||
return expanded;
|
||||
}
|
||||
|
||||
uint HeapRegionManager::expand_any(uint num_regions, WorkGang* pretouch_workers) {
|
||||
uint HeapRegionManager::expand_any(uint num_regions, WorkerThreads* pretouch_workers) {
|
||||
assert(num_regions > 0, "Must expand at least 1 region");
|
||||
|
||||
uint offset = 0;
|
||||
@ -368,7 +368,7 @@ uint HeapRegionManager::expand_any(uint num_regions, WorkGang* pretouch_workers)
|
||||
return expanded;
|
||||
}
|
||||
|
||||
uint HeapRegionManager::expand_by(uint num_regions, WorkGang* pretouch_workers) {
|
||||
uint HeapRegionManager::expand_by(uint num_regions, WorkerThreads* pretouch_workers) {
|
||||
assert(num_regions > 0, "Must expand at least 1 region");
|
||||
|
||||
// First "undo" any requests to uncommit memory concurrently by
|
||||
@ -384,7 +384,7 @@ uint HeapRegionManager::expand_by(uint num_regions, WorkGang* pretouch_workers)
|
||||
return expanded;
|
||||
}
|
||||
|
||||
void HeapRegionManager::expand_exact(uint start, uint num_regions, WorkGang* pretouch_workers) {
|
||||
void HeapRegionManager::expand_exact(uint start, uint num_regions, WorkerThreads* pretouch_workers) {
|
||||
assert(num_regions != 0, "Need to request at least one region");
|
||||
uint end = start + num_regions;
|
||||
|
||||
@ -555,7 +555,7 @@ uint HeapRegionManager::find_highest_free(bool* expanded) {
|
||||
return G1_NO_HRM_INDEX;
|
||||
}
|
||||
|
||||
bool HeapRegionManager::allocate_containing_regions(MemRegion range, size_t* commit_count, WorkGang* pretouch_workers) {
|
||||
bool HeapRegionManager::allocate_containing_regions(MemRegion range, size_t* commit_count, WorkerThreads* pretouch_workers) {
|
||||
size_t commits = 0;
|
||||
uint start_index = (uint)_regions.get_index_by_address(range.start());
|
||||
uint last_index = (uint)_regions.get_index_by_address(range.last());
|
||||
@ -760,7 +760,7 @@ bool HeapRegionClaimer::claim_region(uint region_index) {
|
||||
return old_val == Unclaimed;
|
||||
}
|
||||
|
||||
class G1RebuildFreeListTask : public AbstractGangTask {
|
||||
class G1RebuildFreeListTask : public WorkerTask {
|
||||
HeapRegionManager* _hrm;
|
||||
FreeRegionList* _worker_freelists;
|
||||
uint _worker_chunk_size;
|
||||
@ -768,7 +768,7 @@ class G1RebuildFreeListTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
G1RebuildFreeListTask(HeapRegionManager* hrm, uint num_workers) :
|
||||
AbstractGangTask("G1 Rebuild Free List Task"),
|
||||
WorkerTask("G1 Rebuild Free List Task"),
|
||||
_hrm(hrm),
|
||||
_worker_freelists(NEW_C_HEAP_ARRAY(FreeRegionList, num_workers, mtGC)),
|
||||
_worker_chunk_size((_hrm->reserved_length() + num_workers - 1) / num_workers),
|
||||
@ -818,7 +818,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void HeapRegionManager::rebuild_free_list(WorkGang* workers) {
|
||||
void HeapRegionManager::rebuild_free_list(WorkerThreads* workers) {
|
||||
// Abandon current free list to allow a rebuild.
|
||||
_free_list.abandon();
|
||||
|
||||
|
@ -36,7 +36,7 @@ class HeapRegion;
|
||||
class HeapRegionClosure;
|
||||
class HeapRegionClaimer;
|
||||
class FreeRegionList;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
|
||||
protected:
|
||||
@ -89,7 +89,7 @@ class HeapRegionManager: public CHeapObj<mtGC> {
|
||||
HeapWord* heap_end() const {return _regions.end_address_mapped(); }
|
||||
|
||||
// Pass down commit calls to the VirtualSpace.
|
||||
void commit_regions(uint index, size_t num_regions = 1, WorkGang* pretouch_gang = NULL);
|
||||
void commit_regions(uint index, size_t num_regions = 1, WorkerThreads* pretouch_workers = NULL);
|
||||
|
||||
// Initialize the HeapRegions in the range and put them on the free list.
|
||||
void initialize_regions(uint start, uint num_regions);
|
||||
@ -127,7 +127,7 @@ class HeapRegionManager: public CHeapObj<mtGC> {
|
||||
G1RegionToSpaceMapper* _next_bitmap_mapper;
|
||||
FreeRegionList _free_list;
|
||||
|
||||
void expand(uint index, uint num_regions, WorkGang* pretouch_gang = NULL);
|
||||
void expand(uint index, uint num_regions, WorkerThreads* pretouch_workers = NULL);
|
||||
|
||||
// G1RegionCommittedMap helpers. These functions do the work that comes with
|
||||
// the state changes tracked by G1CommittedRegionMap. To make sure this is
|
||||
@ -147,11 +147,11 @@ class HeapRegionManager: public CHeapObj<mtGC> {
|
||||
HeapRegion* allocate_humongous_allow_expand(uint num_regions);
|
||||
|
||||
// Expand helper for cases when the regions to expand are well defined.
|
||||
void expand_exact(uint start, uint num_regions, WorkGang* pretouch_workers);
|
||||
void expand_exact(uint start, uint num_regions, WorkerThreads* pretouch_workers);
|
||||
// Expand helper activating inactive regions rather than committing new ones.
|
||||
uint expand_inactive(uint num_regions);
|
||||
// Expand helper finding new regions to commit.
|
||||
uint expand_any(uint num_regions, WorkGang* pretouch_workers);
|
||||
uint expand_any(uint num_regions, WorkerThreads* pretouch_workers);
|
||||
|
||||
#ifdef ASSERT
|
||||
public:
|
||||
@ -197,7 +197,7 @@ public:
|
||||
inline void insert_into_free_list(HeapRegion* hr);
|
||||
|
||||
// Rebuild the free region list from scratch.
|
||||
void rebuild_free_list(WorkGang* workers);
|
||||
void rebuild_free_list(WorkerThreads* workers);
|
||||
|
||||
// Insert the given region list into the global free region list.
|
||||
void insert_list_into_free_list(FreeRegionList* list) {
|
||||
@ -253,7 +253,7 @@ public:
|
||||
// HeapRegions, or re-use existing ones. Returns the number of regions the
|
||||
// sequence was expanded by. If a HeapRegion allocation fails, the resulting
|
||||
// number of regions might be smaller than what's desired.
|
||||
uint expand_by(uint num_regions, WorkGang* pretouch_workers);
|
||||
uint expand_by(uint num_regions, WorkerThreads* pretouch_workers);
|
||||
|
||||
// Try to expand on the given node index, returning the index of the new region.
|
||||
uint expand_on_preferred_node(uint node_index);
|
||||
@ -268,7 +268,7 @@ public:
|
||||
// Allocate the regions that contain the address range specified, committing the
|
||||
// regions if necessary. Return false if any of the regions is already committed
|
||||
// and not free, and return the number of regions newly committed in commit_count.
|
||||
bool allocate_containing_regions(MemRegion range, size_t* commit_count, WorkGang* pretouch_workers);
|
||||
bool allocate_containing_regions(MemRegion range, size_t* commit_count, WorkerThreads* pretouch_workers);
|
||||
|
||||
// Apply blk->do_heap_region() on all committed regions in address order,
|
||||
// terminating the iteration early if do_heap_region() returns true.
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
#include "gc/shared/spaceDecorator.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "oops/typeArrayOop.hpp"
|
||||
@ -577,7 +577,7 @@ void MutableNUMASpace::initialize(MemRegion mr,
|
||||
bool clear_space,
|
||||
bool mangle_space,
|
||||
bool setup_pages,
|
||||
WorkGang* pretouch_gang) {
|
||||
WorkerThreads* pretouch_workers) {
|
||||
assert(clear_space, "Reallocation will destroy data!");
|
||||
assert(lgrp_spaces()->length() > 0, "There should be at least one space");
|
||||
|
||||
|
@ -201,7 +201,7 @@ class MutableNUMASpace : public MutableSpace {
|
||||
bool clear_space,
|
||||
bool mangle_space,
|
||||
bool setup_pages = SetupPages,
|
||||
WorkGang* pretouch_gang = NULL);
|
||||
WorkerThreads* pretouch_workers = NULL);
|
||||
// Update space layout if necessary. Do all adaptive resizing job.
|
||||
virtual void update();
|
||||
// Update allocation rate averages.
|
||||
|
@ -72,7 +72,7 @@ void MutableSpace::initialize(MemRegion mr,
|
||||
bool clear_space,
|
||||
bool mangle_space,
|
||||
bool setup_pages,
|
||||
WorkGang* pretouch_gang) {
|
||||
WorkerThreads* pretouch_workers) {
|
||||
|
||||
assert(Universe::on_page_boundary(mr.start()) && Universe::on_page_boundary(mr.end()),
|
||||
"invalid space boundaries");
|
||||
@ -122,10 +122,10 @@ void MutableSpace::initialize(MemRegion mr,
|
||||
size_t page_size = UseLargePages ? os::large_page_size() : os::vm_page_size();
|
||||
|
||||
PretouchTask::pretouch("ParallelGC PreTouch head", (char*)head.start(), (char*)head.end(),
|
||||
page_size, pretouch_gang);
|
||||
page_size, pretouch_workers);
|
||||
|
||||
PretouchTask::pretouch("ParallelGC PreTouch tail", (char*)tail.start(), (char*)tail.end(),
|
||||
page_size, pretouch_gang);
|
||||
page_size, pretouch_workers);
|
||||
}
|
||||
|
||||
// Remember where we stopped so that we can continue later.
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
// A MutableSpace supports the concept of allocation. This includes the
|
||||
// concepts that a space may be only partially full, and the query methods
|
||||
@ -102,7 +102,7 @@ class MutableSpace: public CHeapObj<mtGC> {
|
||||
bool clear_space,
|
||||
bool mangle_space,
|
||||
bool setup_pages = SetupPages,
|
||||
WorkGang* pretouch_gang = NULL);
|
||||
WorkerThreads* pretouch_workers = NULL);
|
||||
|
||||
virtual void clear(bool mangle_space);
|
||||
virtual void update() { }
|
||||
|
@ -85,7 +85,7 @@ jint ParallelScavengeHeap::initialize() {
|
||||
ReservedSpace young_rs = heap_rs.last_part(MaxOldSize);
|
||||
assert(young_rs.size() == MaxNewSize, "Didn't reserve all of the heap");
|
||||
|
||||
// Set up WorkGang
|
||||
// Set up WorkerThreads
|
||||
_workers.initialize_workers();
|
||||
|
||||
// Create and initialize the generations.
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include "gc/shared/referenceProcessor.hpp"
|
||||
#include "gc/shared/softRefPolicy.hpp"
|
||||
#include "gc/shared/strongRootsScope.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/ostream.hpp"
|
||||
@ -91,7 +91,7 @@ class ParallelScavengeHeap : public CollectedHeap {
|
||||
MemoryPool* _survivor_pool;
|
||||
MemoryPool* _old_pool;
|
||||
|
||||
WorkGang _workers;
|
||||
WorkerThreads _workers;
|
||||
|
||||
virtual void initialize_serviceability();
|
||||
|
||||
@ -243,7 +243,7 @@ class ParallelScavengeHeap : public CollectedHeap {
|
||||
virtual void gc_threads_do(ThreadClosure* tc) const;
|
||||
virtual void print_tracing_info() const;
|
||||
|
||||
virtual WorkGang* safepoint_workers() { return &_workers; }
|
||||
virtual WorkerThreads* safepoint_workers() { return &_workers; }
|
||||
|
||||
PreGenGCValues get_pre_gc_values() const;
|
||||
void print_heap_change(const PreGenGCValues& pre_gc_values) const;
|
||||
@ -270,7 +270,7 @@ class ParallelScavengeHeap : public CollectedHeap {
|
||||
GCMemoryManager* old_gc_manager() const { return _old_manager; }
|
||||
GCMemoryManager* young_gc_manager() const { return _young_manager; }
|
||||
|
||||
WorkGang& workers() {
|
||||
WorkerThreads& workers() {
|
||||
return _workers;
|
||||
}
|
||||
};
|
||||
|
@ -67,7 +67,7 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
|
||||
|
||||
_mark_bitmap = mbm;
|
||||
|
||||
uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().total_workers();
|
||||
uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().max_workers();
|
||||
|
||||
assert(_manager_array == NULL, "Attempt to initialize twice");
|
||||
_manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1, mtGC);
|
||||
@ -87,7 +87,7 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
|
||||
// The VMThread gets its own ParCompactionManager, which is not available
|
||||
// for work stealing.
|
||||
_manager_array[parallel_gc_threads] = new ParCompactionManager();
|
||||
assert(ParallelScavengeHeap::heap()->workers().total_workers() != 0,
|
||||
assert(ParallelScavengeHeap::heap()->workers().max_workers() != 0,
|
||||
"Not initialized?");
|
||||
|
||||
_shadow_region_array = new (ResourceObj::C_HEAP, mtGC) GrowableArray<size_t >(10, mtGC);
|
||||
@ -96,14 +96,14 @@ void ParCompactionManager::initialize(ParMarkBitMap* mbm) {
|
||||
}
|
||||
|
||||
void ParCompactionManager::reset_all_bitmap_query_caches() {
|
||||
uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().total_workers();
|
||||
uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().max_workers();
|
||||
for (uint i=0; i<=parallel_gc_threads; i++) {
|
||||
_manager_array[i]->reset_bitmap_query_cache();
|
||||
}
|
||||
}
|
||||
|
||||
void ParCompactionManager::flush_all_string_dedup_requests() {
|
||||
uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().total_workers();
|
||||
uint parallel_gc_threads = ParallelScavengeHeap::heap()->workers().max_workers();
|
||||
for (uint i=0; i<=parallel_gc_threads; i++) {
|
||||
_manager_array[i]->flush_string_dedup_requests();
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ void PSOldGen::post_resize() {
|
||||
start_array()->set_covered_region(new_memregion);
|
||||
ParallelScavengeHeap::heap()->card_table()->resize_covered_region(new_memregion);
|
||||
|
||||
WorkGang* workers = Thread::current()->is_VM_thread() ?
|
||||
WorkerThreads* workers = Thread::current()->is_VM_thread() ?
|
||||
&ParallelScavengeHeap::heap()->workers() : NULL;
|
||||
|
||||
// The update of the space's end is done by this call. As that
|
||||
|
@ -60,7 +60,8 @@
|
||||
#include "gc/shared/taskTerminator.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "gc/shared/workerPolicy.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shared/workerUtils.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "memory/metaspaceUtils.hpp"
|
||||
@ -1765,10 +1766,10 @@ bool PSParallelCompact::invoke_no_policy(bool maximum_heap_compaction) {
|
||||
|
||||
{
|
||||
const uint active_workers =
|
||||
WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().total_workers(),
|
||||
WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().max_workers(),
|
||||
ParallelScavengeHeap::heap()->workers().active_workers(),
|
||||
Threads::number_of_non_daemon_threads());
|
||||
ParallelScavengeHeap::heap()->workers().update_active_workers(active_workers);
|
||||
ParallelScavengeHeap::heap()->workers().set_active_workers(active_workers);
|
||||
|
||||
GCTraceCPUTime tcpu;
|
||||
GCTraceTime(Info, gc) tm("Pause Full", NULL, gc_cause, true);
|
||||
@ -2016,7 +2017,7 @@ void steal_marking_work(TaskTerminator& terminator, uint worker_id) {
|
||||
} while (!terminator.offer_termination());
|
||||
}
|
||||
|
||||
class MarkFromRootsTask : public AbstractGangTask {
|
||||
class MarkFromRootsTask : public WorkerTask {
|
||||
StrongRootsScope _strong_roots_scope; // needed for Threads::possibly_parallel_threads_do
|
||||
OopStorageSetStrongParState<false /* concurrent */, false /* is_const */> _oop_storage_set_par_state;
|
||||
SequentialSubTasksDone _subtasks;
|
||||
@ -2025,7 +2026,7 @@ class MarkFromRootsTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
MarkFromRootsTask(uint active_workers) :
|
||||
AbstractGangTask("MarkFromRootsTask"),
|
||||
WorkerTask("MarkFromRootsTask"),
|
||||
_strong_roots_scope(active_workers),
|
||||
_subtasks(ParallelRootType::sentinel),
|
||||
_terminator(active_workers, ParCompactionManager::oop_task_queues()),
|
||||
@ -2152,7 +2153,7 @@ void PCAdjustPointerClosure::verify_cm(ParCompactionManager* cm) {
|
||||
}
|
||||
#endif
|
||||
|
||||
class PSAdjustTask final : public AbstractGangTask {
|
||||
class PSAdjustTask final : public WorkerTask {
|
||||
SubTasksDone _sub_tasks;
|
||||
WeakProcessor::Task _weak_proc_task;
|
||||
OopStorageSetStrongParState<false, false> _oop_storage_iter;
|
||||
@ -2168,7 +2169,7 @@ class PSAdjustTask final : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
PSAdjustTask(uint nworkers) :
|
||||
AbstractGangTask("PSAdjust task"),
|
||||
WorkerTask("PSAdjust task"),
|
||||
_sub_tasks(PSAdjustSubTask_num_elements),
|
||||
_weak_proc_task(nworkers),
|
||||
_nworkers(nworkers) {
|
||||
@ -2491,14 +2492,14 @@ static void compaction_with_stealing_work(TaskTerminator* terminator, uint worke
|
||||
}
|
||||
}
|
||||
|
||||
class UpdateDensePrefixAndCompactionTask: public AbstractGangTask {
|
||||
class UpdateDensePrefixAndCompactionTask: public WorkerTask {
|
||||
TaskQueue& _tq;
|
||||
TaskTerminator _terminator;
|
||||
uint _active_workers;
|
||||
|
||||
public:
|
||||
UpdateDensePrefixAndCompactionTask(TaskQueue& tq, uint active_workers) :
|
||||
AbstractGangTask("UpdateDensePrefixAndCompactionTask"),
|
||||
WorkerTask("UpdateDensePrefixAndCompactionTask"),
|
||||
_tq(tq),
|
||||
_terminator(active_workers, ParCompactionManager::region_task_queues()),
|
||||
_active_workers(active_workers) {
|
||||
|
@ -54,7 +54,8 @@
|
||||
#include "gc/shared/taskTerminator.hpp"
|
||||
#include "gc/shared/weakProcessor.inline.hpp"
|
||||
#include "gc/shared/workerPolicy.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shared/workerUtils.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "memory/universe.hpp"
|
||||
@ -277,7 +278,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ScavengeRootsTask : public AbstractGangTask {
|
||||
class ScavengeRootsTask : public WorkerTask {
|
||||
StrongRootsScope _strong_roots_scope; // needed for Threads::possibly_parallel_threads_do
|
||||
OopStorageSetStrongParState<false /* concurrent */, false /* is_const */> _oop_storage_strong_par_state;
|
||||
SequentialSubTasksDone _subtasks;
|
||||
@ -292,7 +293,7 @@ public:
|
||||
HeapWord* gen_top,
|
||||
uint active_workers,
|
||||
bool is_empty) :
|
||||
AbstractGangTask("ScavengeRootsTask"),
|
||||
WorkerTask("ScavengeRootsTask"),
|
||||
_strong_roots_scope(active_workers),
|
||||
_subtasks(ParallelRootType::sentinel),
|
||||
_old_gen(old_gen),
|
||||
@ -463,10 +464,10 @@ bool PSScavenge::invoke_no_policy() {
|
||||
HeapWord* old_top = old_gen->object_space()->top();
|
||||
|
||||
const uint active_workers =
|
||||
WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().total_workers(),
|
||||
WorkerPolicy::calc_active_workers(ParallelScavengeHeap::heap()->workers().max_workers(),
|
||||
ParallelScavengeHeap::heap()->workers().active_workers(),
|
||||
Threads::number_of_non_daemon_threads());
|
||||
ParallelScavengeHeap::heap()->workers().update_active_workers(active_workers);
|
||||
ParallelScavengeHeap::heap()->workers().set_active_workers(active_workers);
|
||||
|
||||
PSPromotionManager::pre_scavenge();
|
||||
|
||||
|
@ -189,7 +189,7 @@ void PSYoungGen::set_space_boundaries(size_t eden_size, size_t survivor_size) {
|
||||
MemRegion to_mr ((HeapWord*)to_start, (HeapWord*)from_start);
|
||||
MemRegion from_mr((HeapWord*)from_start, (HeapWord*)from_end);
|
||||
|
||||
WorkGang& pretouch_workers = ParallelScavengeHeap::heap()->workers();
|
||||
WorkerThreads& pretouch_workers = ParallelScavengeHeap::heap()->workers();
|
||||
eden_space()->initialize(eden_mr, true, ZapUnusedHeapArea, MutableSpace::SetupPages, &pretouch_workers);
|
||||
to_space()->initialize(to_mr , true, ZapUnusedHeapArea, MutableSpace::SetupPages, &pretouch_workers);
|
||||
from_space()->initialize(from_mr, true, ZapUnusedHeapArea, MutableSpace::SetupPages, &pretouch_workers);
|
||||
@ -638,7 +638,7 @@ void PSYoungGen::resize_spaces(size_t requested_eden_size,
|
||||
to_space()->check_mangled_unused_area(limit);
|
||||
}
|
||||
|
||||
WorkGang* workers = &ParallelScavengeHeap::heap()->workers();
|
||||
WorkerThreads* workers = &ParallelScavengeHeap::heap()->workers();
|
||||
|
||||
// When an existing space is being initialized, it is not
|
||||
// mangled because the space has been previously mangled.
|
||||
|
@ -44,7 +44,7 @@
|
||||
// class defines the functions that a heap must implement, and contains
|
||||
// infrastructure common to all heaps.
|
||||
|
||||
class AbstractGangTask;
|
||||
class WorkerTask;
|
||||
class AdaptiveSizePolicy;
|
||||
class BarrierSet;
|
||||
class GCHeapLog;
|
||||
@ -59,7 +59,7 @@ class SoftRefPolicy;
|
||||
class Thread;
|
||||
class ThreadClosure;
|
||||
class VirtualSpaceSummary;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
class nmethod;
|
||||
|
||||
class ParallelObjectIterator : public CHeapObj<mtGC> {
|
||||
@ -469,7 +469,7 @@ class CollectedHeap : public CHeapObj<mtInternal> {
|
||||
// concurrent marking) for an intermittent non-GC safepoint.
|
||||
// If this method returns NULL, SafepointSynchronize will
|
||||
// perform cleanup tasks serially in the VMThread.
|
||||
virtual WorkGang* safepoint_workers() { return NULL; }
|
||||
virtual WorkerThreads* safepoint_workers() { return NULL; }
|
||||
|
||||
// Support for object pinning. This is used by JNI Get*Critical()
|
||||
// and Release*Critical() family of functions. If supported, the GC
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include "gc/shared/space.hpp"
|
||||
#include "gc/shared/strongRootsScope.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/metaspaceCounters.hpp"
|
||||
#include "memory/metaspaceUtils.hpp"
|
||||
|
@ -37,7 +37,7 @@ class GCPolicyCounters;
|
||||
class GenerationSpec;
|
||||
class StrongRootsScope;
|
||||
class SubTasksDone;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
// A "GenCollectedHeap" is a CollectedHeap that uses generational
|
||||
// collection. It has two generations, young and old.
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "classfile/classLoaderDataGraph.hpp"
|
||||
#include "code/codeCache.hpp"
|
||||
#include "gc/shared/oopStorageParState.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
|
||||
class CodeCacheUnloadingTask {
|
||||
|
||||
|
@ -24,7 +24,8 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/preservedMarks.inline.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shared/workerUtils.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
@ -92,7 +93,7 @@ void PreservedMarksSet::init(uint num) {
|
||||
assert_empty();
|
||||
}
|
||||
|
||||
class RestorePreservedMarksTask : public AbstractGangTask {
|
||||
class RestorePreservedMarksTask : public WorkerTask {
|
||||
PreservedMarksSet* const _preserved_marks_set;
|
||||
SequentialSubTasksDone _sub_tasks;
|
||||
volatile size_t _total_size;
|
||||
@ -109,7 +110,7 @@ public:
|
||||
}
|
||||
|
||||
RestorePreservedMarksTask(PreservedMarksSet* preserved_marks_set)
|
||||
: AbstractGangTask("Restore Preserved Marks"),
|
||||
: WorkerTask("Restore Preserved Marks"),
|
||||
_preserved_marks_set(preserved_marks_set),
|
||||
_sub_tasks(preserved_marks_set->num()),
|
||||
_total_size(0)
|
||||
@ -129,7 +130,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void PreservedMarksSet::restore(WorkGang* workers) {
|
||||
void PreservedMarksSet::restore(WorkerThreads* workers) {
|
||||
{
|
||||
RestorePreservedMarksTask cl(this);
|
||||
if (workers == nullptr) {
|
||||
@ -142,7 +143,7 @@ void PreservedMarksSet::restore(WorkGang* workers) {
|
||||
assert_empty();
|
||||
}
|
||||
|
||||
AbstractGangTask* PreservedMarksSet::create_task() {
|
||||
WorkerTask* PreservedMarksSet::create_task() {
|
||||
return new RestorePreservedMarksTask(this);
|
||||
}
|
||||
|
||||
|
@ -30,9 +30,9 @@
|
||||
#include "oops/oop.hpp"
|
||||
#include "utilities/stack.hpp"
|
||||
|
||||
class AbstractGangTask;
|
||||
class WorkerTask;
|
||||
class PreservedMarksSet;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
class PreservedMarks {
|
||||
private:
|
||||
@ -110,11 +110,11 @@ public:
|
||||
void init(uint num);
|
||||
|
||||
// Iterate over all stacks, restore all preserved marks, and reclaim
|
||||
// the memory taken up by the stack segments using the given WorkGang. If the WorkGang
|
||||
// the memory taken up by the stack segments using the given WorkerThreads. If the WorkerThreads
|
||||
// is NULL, perform the work serially in the current thread.
|
||||
void restore(WorkGang* workers);
|
||||
void restore(WorkerThreads* workers);
|
||||
|
||||
AbstractGangTask* create_task();
|
||||
WorkerTask* create_task();
|
||||
|
||||
// Reclaim stack array.
|
||||
void reclaim();
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
#include "gc/shared/pretouchTask.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
@ -34,7 +35,7 @@ PretouchTask::PretouchTask(const char* task_name,
|
||||
char* end_address,
|
||||
size_t page_size,
|
||||
size_t chunk_size) :
|
||||
AbstractGangTask(task_name),
|
||||
WorkerTask(task_name),
|
||||
_cur_addr(start_address),
|
||||
_end_addr(end_address),
|
||||
_page_size(page_size),
|
||||
@ -62,7 +63,7 @@ void PretouchTask::work(uint worker_id) {
|
||||
}
|
||||
|
||||
void PretouchTask::pretouch(const char* task_name, char* start_address, char* end_address,
|
||||
size_t page_size, WorkGang* pretouch_gang) {
|
||||
size_t page_size, WorkerThreads* pretouch_workers) {
|
||||
// Chunk size should be at least (unmodified) page size as using multiple threads
|
||||
// pretouch on a single page can decrease performance.
|
||||
size_t chunk_size = MAX2(PretouchTask::chunk_size(), page_size);
|
||||
@ -79,14 +80,14 @@ void PretouchTask::pretouch(const char* task_name, char* start_address, char* en
|
||||
return;
|
||||
}
|
||||
|
||||
if (pretouch_gang != NULL) {
|
||||
if (pretouch_workers != NULL) {
|
||||
size_t num_chunks = (total_bytes + chunk_size - 1) / chunk_size;
|
||||
|
||||
uint num_workers = (uint)MIN2(num_chunks, (size_t)pretouch_gang->total_workers());
|
||||
uint num_workers = (uint)MIN2(num_chunks, (size_t)pretouch_workers->max_workers());
|
||||
log_debug(gc, heap)("Running %s with %u workers for " SIZE_FORMAT " work units pre-touching " SIZE_FORMAT "B.",
|
||||
task.name(), num_workers, num_chunks, total_bytes);
|
||||
|
||||
pretouch_gang->run_task(&task, num_workers);
|
||||
pretouch_workers->run_task(&task, num_workers);
|
||||
} else {
|
||||
log_debug(gc, heap)("Running %s pre-touching " SIZE_FORMAT "B.",
|
||||
task.name(), total_bytes);
|
||||
|
@ -25,9 +25,9 @@
|
||||
#ifndef SHARE_GC_SHARED_PRETOUCH_HPP
|
||||
#define SHARE_GC_SHARED_PRETOUCH_HPP
|
||||
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
|
||||
class PretouchTask : public AbstractGangTask {
|
||||
class PretouchTask : public WorkerTask {
|
||||
char* volatile _cur_addr;
|
||||
char* const _end_addr;
|
||||
size_t _page_size;
|
||||
@ -41,7 +41,7 @@ public:
|
||||
static size_t chunk_size();
|
||||
|
||||
static void pretouch(const char* task_name, char* start_address, char* end_address,
|
||||
size_t page_size, WorkGang* pretouch_gang);
|
||||
size_t page_size, WorkerThreads* pretouch_workers);
|
||||
|
||||
};
|
||||
|
||||
|
@ -705,12 +705,12 @@ void ReferenceProcessor::run_task(RefProcTask& task, RefProcProxyTask& proxy_tas
|
||||
|
||||
proxy_task.prepare_run_task(task, num_queues(), processing_is_mt() ? RefProcThreadModel::Multi : RefProcThreadModel::Single, marks_oops_alive);
|
||||
if (processing_is_mt()) {
|
||||
WorkGang* gang = Universe::heap()->safepoint_workers();
|
||||
assert(gang != NULL, "can not dispatch multi threaded without a work gang");
|
||||
assert(gang->active_workers() >= num_queues(),
|
||||
WorkerThreads* workers = Universe::heap()->safepoint_workers();
|
||||
assert(workers != NULL, "can not dispatch multi threaded without workers");
|
||||
assert(workers->active_workers() >= num_queues(),
|
||||
"Ergonomically chosen workers(%u) should be less than or equal to active workers(%u)",
|
||||
num_queues(), gang->active_workers());
|
||||
gang->run_task(&proxy_task, num_queues());
|
||||
num_queues(), workers->active_workers());
|
||||
workers->run_task(&proxy_task, num_queues());
|
||||
} else {
|
||||
for (unsigned i = 0; i < _max_num_queues; ++i) {
|
||||
proxy_task.work(i);
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "gc/shared/referenceDiscoverer.hpp"
|
||||
#include "gc/shared/referencePolicy.hpp"
|
||||
#include "gc/shared/referenceProcessorStats.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/referenceType.hpp"
|
||||
#include "oops/instanceRefKlass.hpp"
|
||||
|
||||
@ -589,7 +589,7 @@ public:
|
||||
* of RefProcTask that will handle reference processing in a generic way for Serial,
|
||||
* Parallel and G1. This proxy will add the relevant closures, task terminators etc.
|
||||
*/
|
||||
class RefProcProxyTask : public AbstractGangTask {
|
||||
class RefProcProxyTask : public WorkerTask {
|
||||
protected:
|
||||
const uint _max_workers;
|
||||
RefProcTask* _rp_task;
|
||||
@ -598,7 +598,7 @@ protected:
|
||||
bool _marks_oops_alive;
|
||||
|
||||
public:
|
||||
RefProcProxyTask(const char* name, uint max_workers) : AbstractGangTask(name), _max_workers(max_workers), _rp_task(nullptr),_tm(RefProcThreadModel::Single), _queue_count(0), _marks_oops_alive(false) {}
|
||||
RefProcProxyTask(const char* name, uint max_workers) : WorkerTask(name), _max_workers(max_workers), _rp_task(nullptr),_tm(RefProcThreadModel::Single), _queue_count(0), _marks_oops_alive(false) {}
|
||||
|
||||
void prepare_run_task(RefProcTask& rp_task, uint queue_count, RefProcThreadModel tm, bool marks_oops_alive) {
|
||||
_rp_task = &rp_task;
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "gc/shared/blockOffsetTable.hpp"
|
||||
#include "gc/shared/cardTable.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "memory/memRegion.hpp"
|
||||
|
@ -125,6 +125,6 @@ void WeakProcessor::Task::report_num_dead() {
|
||||
_storage_states.report_num_dead();
|
||||
}
|
||||
|
||||
void WeakProcessor::GangTask::work(uint worker_id) {
|
||||
void WeakProcessor::WeakOopsDoTask::work(uint worker_id) {
|
||||
_erased_do_work(this, worker_id);
|
||||
}
|
||||
|
@ -27,11 +27,11 @@
|
||||
|
||||
#include "gc/shared/oopStorageParState.hpp"
|
||||
#include "gc/shared/oopStorageSetParState.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
class WeakProcessorTimes;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
// Helper class to aid in root scanning and cleaning of weak oops in the VM.
|
||||
//
|
||||
@ -53,7 +53,7 @@ public:
|
||||
// IsAlive must be derived from BoolObjectClosure.
|
||||
// KeepAlive must be derived from OopClosure.
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
static void weak_oops_do(WorkGang* workers,
|
||||
static void weak_oops_do(WorkerThreads* workers,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
WeakProcessorTimes* times);
|
||||
@ -64,7 +64,7 @@ public:
|
||||
// IsAlive must be derived from BoolObjectClosure.
|
||||
// KeepAlive must be derived from OopClosure.
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
static void weak_oops_do(WorkGang* workers,
|
||||
static void weak_oops_do(WorkerThreads* workers,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
uint indent_log);
|
||||
@ -79,7 +79,7 @@ private:
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
class CountingClosure;
|
||||
|
||||
class GangTask;
|
||||
class WeakOopsDoTask;
|
||||
};
|
||||
|
||||
class WeakProcessor::Task {
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "gc/shared/oopStorageParState.inline.hpp"
|
||||
#include "gc/shared/oopStorageSet.hpp"
|
||||
#include "gc/shared/weakProcessorTimes.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "prims/resolvedMethodTable.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/enumIterator.hpp"
|
||||
@ -96,14 +96,14 @@ void WeakProcessor::Task::work(uint worker_id,
|
||||
}
|
||||
}
|
||||
|
||||
class WeakProcessor::GangTask : public AbstractGangTask {
|
||||
class WeakProcessor::WeakOopsDoTask : public WorkerTask {
|
||||
Task _task;
|
||||
BoolObjectClosure* _is_alive;
|
||||
OopClosure* _keep_alive;
|
||||
void (*_erased_do_work)(GangTask* task, uint worker_id);
|
||||
void (*_erased_do_work)(WeakOopsDoTask* task, uint worker_id);
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
static void erased_do_work(GangTask* task, uint worker_id) {
|
||||
static void erased_do_work(WeakOopsDoTask* task, uint worker_id) {
|
||||
task->_task.work(worker_id,
|
||||
static_cast<IsAlive*>(task->_is_alive),
|
||||
static_cast<KeepAlive*>(task->_keep_alive));
|
||||
@ -111,12 +111,12 @@ class WeakProcessor::GangTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
GangTask(const char* name,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
WeakProcessorTimes* times,
|
||||
uint nworkers) :
|
||||
AbstractGangTask(name),
|
||||
WeakOopsDoTask(const char* name,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
WeakProcessorTimes* times,
|
||||
uint nworkers) :
|
||||
WorkerTask(name),
|
||||
_task(times, nworkers),
|
||||
_is_alive(is_alive),
|
||||
_keep_alive(keep_alive),
|
||||
@ -128,26 +128,26 @@ public:
|
||||
};
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
void WeakProcessor::weak_oops_do(WorkGang* workers,
|
||||
void WeakProcessor::weak_oops_do(WorkerThreads* workers,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
WeakProcessorTimes* times) {
|
||||
WeakProcessorTimeTracker tt(times);
|
||||
|
||||
uint nworkers = ergo_workers(MIN2(workers->total_workers(),
|
||||
uint nworkers = ergo_workers(MIN2(workers->max_workers(),
|
||||
times->max_threads()));
|
||||
|
||||
GangTask task("Weak Processor", is_alive, keep_alive, times, nworkers);
|
||||
WeakOopsDoTask task("Weak Processor", is_alive, keep_alive, times, nworkers);
|
||||
workers->run_task(&task, nworkers);
|
||||
task.report_num_dead();
|
||||
}
|
||||
|
||||
template<typename IsAlive, typename KeepAlive>
|
||||
void WeakProcessor::weak_oops_do(WorkGang* workers,
|
||||
void WeakProcessor::weak_oops_do(WorkerThreads* workers,
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
uint indent_log) {
|
||||
uint nworkers = ergo_workers(workers->total_workers());
|
||||
uint nworkers = ergo_workers(workers->max_workers());
|
||||
WeakProcessorTimes times(nworkers);
|
||||
weak_oops_do(workers, is_alive, keep_alive, ×);
|
||||
times.log_subtotals(indent_log); // Caller logs total if desired.
|
||||
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_SHARED_WORKERMANAGER_HPP
|
||||
#define SHARE_GC_SHARED_WORKERMANAGER_HPP
|
||||
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
class WorkerManager : public AllStatic {
|
||||
public:
|
||||
// Create additional workers as needed.
|
||||
// active_workers - number of workers being requested for an upcoming
|
||||
// parallel task.
|
||||
// total_workers - total number of workers. This is the maximum
|
||||
// number possible.
|
||||
// created_workers - number of workers already created. This maybe
|
||||
// less than, equal to, or greater than active workers. If greater than
|
||||
// or equal to active_workers, nothing is done.
|
||||
// worker_type - type of thread.
|
||||
// initializing - true if this is called to get the initial number of
|
||||
// GC workers.
|
||||
// If initializing is true, do a vm exit if the workers cannot be created.
|
||||
// The initializing = true case is for JVM start up and failing to
|
||||
// create all the worker at start should considered a problem so exit.
|
||||
// If initializing = false, there are already some number of worker
|
||||
// threads and a failure would not be optimal but should not be fatal.
|
||||
static uint add_workers (WorkGang* workers,
|
||||
uint active_workers,
|
||||
uint total_workers,
|
||||
uint created_workers,
|
||||
os::ThreadType worker_type,
|
||||
bool initializing);
|
||||
|
||||
// Log (at trace level) a change in the number of created workers.
|
||||
static void log_worker_creation(WorkGang* workers,
|
||||
uint previous_created_workers,
|
||||
uint active_workers,
|
||||
uint created_workers,
|
||||
bool initializing);
|
||||
};
|
||||
|
||||
uint WorkerManager::add_workers(WorkGang* workers,
|
||||
uint active_workers,
|
||||
uint total_workers,
|
||||
uint created_workers,
|
||||
os::ThreadType worker_type,
|
||||
bool initializing) {
|
||||
uint start = created_workers;
|
||||
uint end = MIN2(active_workers, total_workers);
|
||||
for (uint worker_id = start; worker_id < end; worker_id += 1) {
|
||||
WorkerThread* new_worker = NULL;
|
||||
if (initializing || !InjectGCWorkerCreationFailure) {
|
||||
new_worker = workers->install_worker(worker_id);
|
||||
}
|
||||
if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) {
|
||||
log_trace(gc, task)("WorkerManager::add_workers() : "
|
||||
"creation failed due to failed allocation of native %s",
|
||||
new_worker == NULL ? "memory" : "thread");
|
||||
delete new_worker;
|
||||
if (initializing) {
|
||||
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create worker GC thread. Out of system resources.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
created_workers++;
|
||||
os::start_thread(new_worker);
|
||||
}
|
||||
|
||||
log_trace(gc, task)("WorkerManager::add_workers() : "
|
||||
"created_workers: %u", created_workers);
|
||||
|
||||
return created_workers;
|
||||
}
|
||||
|
||||
void WorkerManager::log_worker_creation(WorkGang* workers,
|
||||
uint previous_created_workers,
|
||||
uint active_workers,
|
||||
uint created_workers,
|
||||
bool initializing) {
|
||||
if (previous_created_workers < created_workers) {
|
||||
const char* initializing_msg = initializing ? "Adding initial" : "Creating additional";
|
||||
log_trace(gc, task)("%s %s(s) previously created workers %u active workers %u total created workers %u",
|
||||
initializing_msg, workers->group_name(), previous_created_workers, active_workers, created_workers);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SHARE_GC_SHARED_WORKERMANAGER_HPP
|
161
src/hotspot/share/gc/shared/workerThread.cpp
Normal file
161
src/hotspot/share/gc/shared/workerThread.cpp
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/gc_globals.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/init.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
|
||||
WorkerTaskDispatcher::WorkerTaskDispatcher() :
|
||||
_task(NULL),
|
||||
_started(0),
|
||||
_not_finished(0),
|
||||
_start_semaphore(),
|
||||
_end_semaphore() {}
|
||||
|
||||
void WorkerTaskDispatcher::coordinator_distribute_task(WorkerTask* task, uint num_workers) {
|
||||
// No workers are allowed to read the state variables until they have been signaled.
|
||||
_task = task;
|
||||
_not_finished = num_workers;
|
||||
|
||||
// Dispatch 'num_workers' number of tasks.
|
||||
_start_semaphore.signal(num_workers);
|
||||
|
||||
// Wait for the last worker to signal the coordinator.
|
||||
_end_semaphore.wait();
|
||||
|
||||
// No workers are allowed to read the state variables after the coordinator has been signaled.
|
||||
assert(_not_finished == 0, "%d not finished workers?", _not_finished);
|
||||
_task = NULL;
|
||||
_started = 0;
|
||||
}
|
||||
|
||||
void WorkerTaskDispatcher::worker_run_task() {
|
||||
// Wait for the coordinator to dispatch a task.
|
||||
_start_semaphore.wait();
|
||||
|
||||
// Get worker id.
|
||||
const uint worker_id = Atomic::fetch_and_add(&_started, 1u);
|
||||
|
||||
// Run task.
|
||||
GCIdMark gc_id_mark(_task->gc_id());
|
||||
_task->work(worker_id);
|
||||
|
||||
// Mark that the worker is done with the task.
|
||||
// The worker is not allowed to read the state variables after this line.
|
||||
const uint not_finished = Atomic::sub(&_not_finished, 1u);
|
||||
|
||||
// The last worker signals to the coordinator that all work is completed.
|
||||
if (not_finished == 0) {
|
||||
_end_semaphore.signal();
|
||||
}
|
||||
}
|
||||
|
||||
WorkerThreads::WorkerThreads(const char* name, uint max_workers) :
|
||||
_name(name),
|
||||
_workers(NEW_C_HEAP_ARRAY(WorkerThread*, max_workers, mtInternal)),
|
||||
_max_workers(max_workers),
|
||||
_created_workers(0),
|
||||
_active_workers(0),
|
||||
_dispatcher() {}
|
||||
|
||||
void WorkerThreads::initialize_workers() {
|
||||
const uint initial_active_workers = UseDynamicNumberOfGCThreads ? 1 : _max_workers;
|
||||
if (set_active_workers(initial_active_workers) != initial_active_workers) {
|
||||
vm_exit_during_initialization();
|
||||
}
|
||||
}
|
||||
|
||||
WorkerThread* WorkerThreads::create_worker(uint id) {
|
||||
if (is_init_completed() && InjectGCWorkerCreationFailure) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
WorkerThread* const worker = new WorkerThread(_name, id, &_dispatcher);
|
||||
|
||||
if (!os::create_thread(worker, os::gc_thread)) {
|
||||
delete worker;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
os::start_thread(worker);
|
||||
|
||||
return worker;
|
||||
}
|
||||
|
||||
uint WorkerThreads::set_active_workers(uint num_workers) {
|
||||
assert(num_workers > 0 && num_workers <= _max_workers,
|
||||
"Invalid number of active workers %u (should be 1-%u)",
|
||||
num_workers, _max_workers);
|
||||
|
||||
while (_created_workers < num_workers) {
|
||||
WorkerThread* const worker = create_worker(_created_workers);
|
||||
if (worker == NULL) {
|
||||
log_error(gc, task)("Failed to create worker thread");
|
||||
break;
|
||||
}
|
||||
|
||||
_workers[_created_workers] = worker;
|
||||
_created_workers++;
|
||||
}
|
||||
|
||||
_active_workers = MIN2(_created_workers, num_workers);
|
||||
|
||||
log_trace(gc, task)("%s: using %d out of %d workers", _name, _active_workers, _max_workers);
|
||||
|
||||
return _active_workers;
|
||||
}
|
||||
|
||||
void WorkerThreads::threads_do(ThreadClosure* tc) const {
|
||||
for (uint i = 0; i < _created_workers; i++) {
|
||||
tc->do_thread(_workers[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void WorkerThreads::run_task(WorkerTask* task) {
|
||||
_dispatcher.coordinator_distribute_task(task, _active_workers);
|
||||
}
|
||||
|
||||
void WorkerThreads::run_task(WorkerTask* task, uint num_workers) {
|
||||
WithActiveWorkers with_active_workers(this, num_workers);
|
||||
run_task(task);
|
||||
}
|
||||
|
||||
WorkerThread::WorkerThread(const char* name_prefix, uint id, WorkerTaskDispatcher* dispatcher) :
|
||||
_dispatcher(dispatcher),
|
||||
_id(id) {
|
||||
set_name("%s#%d", name_prefix, id);
|
||||
}
|
||||
|
||||
void WorkerThread::run() {
|
||||
os::set_priority(this, NearMaxPriority);
|
||||
|
||||
while (true) {
|
||||
_dispatcher->worker_run_task();
|
||||
}
|
||||
}
|
164
src/hotspot/share/gc/shared/workerThread.hpp
Normal file
164
src/hotspot/share/gc/shared/workerThread.hpp
Normal file
@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_SHARED_WORKERTHREAD_HPP
|
||||
#define SHARE_GC_SHARED_WORKERTHREAD_HPP
|
||||
|
||||
#include "gc/shared/gcId.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/nonJavaThread.hpp"
|
||||
#include "runtime/semaphore.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
class ThreadClosure;
|
||||
class WorkerTaskDispatcher;
|
||||
class WorkerThread;
|
||||
|
||||
// An task to be worked on by worker threads
|
||||
class WorkerTask : public CHeapObj<mtInternal> {
|
||||
private:
|
||||
const char* _name;
|
||||
const uint _gc_id;
|
||||
|
||||
public:
|
||||
explicit WorkerTask(const char* name) :
|
||||
_name(name),
|
||||
_gc_id(GCId::current_or_undefined()) {}
|
||||
|
||||
const char* name() const { return _name; }
|
||||
const uint gc_id() const { return _gc_id; }
|
||||
|
||||
virtual void work(uint worker_id) = 0;
|
||||
};
|
||||
|
||||
// WorkerThreads dispatcher implemented with semaphores
|
||||
class WorkerTaskDispatcher {
|
||||
// The task currently being dispatched to the WorkerThreads.
|
||||
WorkerTask* _task;
|
||||
|
||||
volatile uint _started;
|
||||
volatile uint _not_finished;
|
||||
|
||||
// Semaphore used to start the WorkerThreads.
|
||||
Semaphore _start_semaphore;
|
||||
// Semaphore used to notify the coordinator that all workers are done.
|
||||
Semaphore _end_semaphore;
|
||||
|
||||
public:
|
||||
WorkerTaskDispatcher();
|
||||
|
||||
// Coordinator API.
|
||||
|
||||
// Distributes the task out to num_workers workers.
|
||||
// Returns when the task has been completed by all workers.
|
||||
void coordinator_distribute_task(WorkerTask* task, uint num_workers);
|
||||
|
||||
// Worker API.
|
||||
|
||||
// Waits for a task to become available to the worker and runs it.
|
||||
void worker_run_task();
|
||||
};
|
||||
|
||||
// A set of worker threads to execute tasks
|
||||
class WorkerThreads : public CHeapObj<mtInternal> {
|
||||
private:
|
||||
const char* const _name;
|
||||
WorkerThread** _workers;
|
||||
const uint _max_workers;
|
||||
uint _created_workers;
|
||||
uint _active_workers;
|
||||
WorkerTaskDispatcher _dispatcher;
|
||||
|
||||
protected:
|
||||
virtual WorkerThread* create_worker(uint id);
|
||||
|
||||
public:
|
||||
WorkerThreads(const char* name, uint max_workers);
|
||||
|
||||
void initialize_workers();
|
||||
|
||||
uint max_workers() const { return _max_workers; }
|
||||
uint created_workers() const { return _created_workers; }
|
||||
uint active_workers() const { return _active_workers; }
|
||||
|
||||
uint set_active_workers(uint num_workers);
|
||||
|
||||
void threads_do(ThreadClosure* tc) const;
|
||||
|
||||
const char* name() const { return _name; }
|
||||
|
||||
// Run a task using the current active number of workers, returns when the task is done.
|
||||
void run_task(WorkerTask* task);
|
||||
|
||||
// Run a task with the given number of workers, returns when the task is done.
|
||||
void run_task(WorkerTask* task, uint num_workers);
|
||||
};
|
||||
|
||||
class WorkerThread : public NamedThread {
|
||||
private:
|
||||
WorkerTaskDispatcher* const _dispatcher;
|
||||
const uint _id;
|
||||
|
||||
public:
|
||||
static WorkerThread* current() {
|
||||
return WorkerThread::cast(Thread::current());
|
||||
}
|
||||
|
||||
static WorkerThread* cast(Thread* t) {
|
||||
assert(t->is_Worker_thread(), "incorrect cast to WorkerThread");
|
||||
return static_cast<WorkerThread*>(t);
|
||||
}
|
||||
|
||||
WorkerThread(const char* name_prefix, uint id, WorkerTaskDispatcher* dispatcher);
|
||||
|
||||
uint id() const { return _id; }
|
||||
|
||||
bool is_Worker_thread() const override { return true; }
|
||||
const char* type_name() const override { return "WorkerThread"; }
|
||||
|
||||
void run() override;
|
||||
};
|
||||
|
||||
// Temporarily try to set the number of active workers.
|
||||
// It's not guaranteed that it succeeds, and users need to
|
||||
// query the number of active workers.
|
||||
class WithActiveWorkers : public StackObj {
|
||||
private:
|
||||
WorkerThreads* const _workers;
|
||||
const uint _prev_active_workers;
|
||||
|
||||
public:
|
||||
WithActiveWorkers(WorkerThreads* workers, uint num_workers) :
|
||||
_workers(workers),
|
||||
_prev_active_workers(workers->active_workers()) {
|
||||
_workers->set_active_workers(num_workers);
|
||||
}
|
||||
|
||||
~WithActiveWorkers() {
|
||||
_workers->set_active_workers(_prev_active_workers);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SHARED_WORKERTHREAD_HPP
|
136
src/hotspot/share/gc/shared/workerUtils.cpp
Normal file
136
src/hotspot/share/gc/shared/workerUtils.cpp
Normal file
@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/workerUtils.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/mutexLocker.hpp"
|
||||
|
||||
// *** WorkerThreadsBarrierSync
|
||||
|
||||
WorkerThreadsBarrierSync::WorkerThreadsBarrierSync()
|
||||
: _monitor(Mutex::nosafepoint, "WorkerThreadsBarrierSync_lock"),
|
||||
_n_workers(0), _n_completed(0), _should_reset(false), _aborted(false) {
|
||||
}
|
||||
|
||||
void WorkerThreadsBarrierSync::set_n_workers(uint n_workers) {
|
||||
_n_workers = n_workers;
|
||||
_n_completed = 0;
|
||||
_should_reset = false;
|
||||
_aborted = false;
|
||||
}
|
||||
|
||||
bool WorkerThreadsBarrierSync::enter() {
|
||||
MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
|
||||
if (should_reset()) {
|
||||
// The should_reset() was set and we are the first worker to enter
|
||||
// the sync barrier. We will zero the n_completed() count which
|
||||
// effectively resets the barrier.
|
||||
zero_completed();
|
||||
set_should_reset(false);
|
||||
}
|
||||
inc_completed();
|
||||
if (n_completed() == n_workers()) {
|
||||
// At this point we would like to reset the barrier to be ready in
|
||||
// case it is used again. However, we cannot set n_completed() to
|
||||
// 0, even after the notify_all(), given that some other workers
|
||||
// might still be waiting for n_completed() to become ==
|
||||
// n_workers(). So, if we set n_completed() to 0, those workers
|
||||
// will get stuck (as they will wake up, see that n_completed() !=
|
||||
// n_workers() and go back to sleep). Instead, we raise the
|
||||
// should_reset() flag and the barrier will be reset the first
|
||||
// time a worker enters it again.
|
||||
set_should_reset(true);
|
||||
ml.notify_all();
|
||||
} else {
|
||||
while (n_completed() != n_workers() && !aborted()) {
|
||||
ml.wait();
|
||||
}
|
||||
}
|
||||
return !aborted();
|
||||
}
|
||||
|
||||
void WorkerThreadsBarrierSync::abort() {
|
||||
MutexLocker x(monitor(), Mutex::_no_safepoint_check_flag);
|
||||
set_aborted();
|
||||
monitor()->notify_all();
|
||||
}
|
||||
|
||||
// SubTasksDone functions.
|
||||
|
||||
SubTasksDone::SubTasksDone(uint n) :
|
||||
_tasks(NULL), _n_tasks(n) {
|
||||
_tasks = NEW_C_HEAP_ARRAY(bool, n, mtInternal);
|
||||
for (uint i = 0; i < _n_tasks; i++) {
|
||||
_tasks[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
void SubTasksDone::all_tasks_claimed_impl(uint skipped[], size_t skipped_size) {
|
||||
if (Atomic::cmpxchg(&_verification_done, false, true)) {
|
||||
// another thread has done the verification
|
||||
return;
|
||||
}
|
||||
// all non-skipped tasks are claimed
|
||||
for (uint i = 0; i < _n_tasks; ++i) {
|
||||
if (!_tasks[i]) {
|
||||
auto is_skipped = false;
|
||||
for (size_t j = 0; j < skipped_size; ++j) {
|
||||
if (i == skipped[j]) {
|
||||
is_skipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(is_skipped, "%d not claimed.", i);
|
||||
}
|
||||
}
|
||||
// all skipped tasks are *not* claimed
|
||||
for (size_t i = 0; i < skipped_size; ++i) {
|
||||
auto task_index = skipped[i];
|
||||
assert(task_index < _n_tasks, "Array in range.");
|
||||
assert(!_tasks[task_index], "%d is both claimed and skipped.", task_index);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SubTasksDone::try_claim_task(uint t) {
|
||||
assert(t < _n_tasks, "bad task id.");
|
||||
return !_tasks[t] && !Atomic::cmpxchg(&_tasks[t], false, true);
|
||||
}
|
||||
|
||||
SubTasksDone::~SubTasksDone() {
|
||||
assert(_verification_done, "all_tasks_claimed must have been called.");
|
||||
FREE_C_HEAP_ARRAY(bool, _tasks);
|
||||
}
|
||||
|
||||
// *** SequentialSubTasksDone
|
||||
|
||||
bool SequentialSubTasksDone::try_claim_task(uint& t) {
|
||||
t = _num_claimed;
|
||||
if (t < _num_tasks) {
|
||||
t = Atomic::add(&_num_claimed, 1u) - 1;
|
||||
}
|
||||
return t < _num_tasks;
|
||||
}
|
148
src/hotspot/share/gc/shared/workerUtils.hpp
Normal file
148
src/hotspot/share/gc/shared/workerUtils.hpp
Normal file
@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_SHARED_WORKERUTILS_HPP
|
||||
#define SHARE_GC_SHARED_WORKERUTILS_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "metaprogramming/enableIf.hpp"
|
||||
#include "metaprogramming/logical.hpp"
|
||||
#include "runtime/mutex.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
// A class that acts as a synchronisation barrier. Workers enter
|
||||
// the barrier and must wait until all other workers have entered
|
||||
// before any of them may leave.
|
||||
|
||||
class WorkerThreadsBarrierSync : public StackObj {
|
||||
protected:
|
||||
Monitor _monitor;
|
||||
uint _n_workers;
|
||||
uint _n_completed;
|
||||
bool _should_reset;
|
||||
bool _aborted;
|
||||
|
||||
Monitor* monitor() { return &_monitor; }
|
||||
uint n_workers() { return _n_workers; }
|
||||
uint n_completed() { return _n_completed; }
|
||||
bool should_reset() { return _should_reset; }
|
||||
bool aborted() { return _aborted; }
|
||||
|
||||
void zero_completed() { _n_completed = 0; }
|
||||
void inc_completed() { _n_completed++; }
|
||||
void set_aborted() { _aborted = true; }
|
||||
void set_should_reset(bool v) { _should_reset = v; }
|
||||
|
||||
public:
|
||||
WorkerThreadsBarrierSync();
|
||||
|
||||
// Set the number of workers that will use the barrier.
|
||||
// Must be called before any of the workers start running.
|
||||
void set_n_workers(uint n_workers);
|
||||
|
||||
// Enter the barrier. A worker that enters the barrier will
|
||||
// not be allowed to leave until all other threads have
|
||||
// also entered the barrier or the barrier is aborted.
|
||||
// Returns false if the barrier was aborted.
|
||||
bool enter();
|
||||
|
||||
// Aborts the barrier and wakes up any threads waiting for
|
||||
// the barrier to complete. The barrier will remain in the
|
||||
// aborted state until the next call to set_n_workers().
|
||||
void abort();
|
||||
};
|
||||
|
||||
// A class to manage claiming of subtasks within a group of tasks. The
|
||||
// subtasks will be identified by integer indices, usually elements of an
|
||||
// enumeration type.
|
||||
|
||||
class SubTasksDone: public CHeapObj<mtInternal> {
|
||||
volatile bool* _tasks;
|
||||
uint _n_tasks;
|
||||
|
||||
// make sure verification logic is run exactly once to avoid duplicate assertion failures
|
||||
DEBUG_ONLY(volatile bool _verification_done = false;)
|
||||
void all_tasks_claimed_impl(uint skipped[], size_t skipped_size) NOT_DEBUG_RETURN;
|
||||
|
||||
NONCOPYABLE(SubTasksDone);
|
||||
|
||||
public:
|
||||
// Initializes "this" to a state in which there are "n" tasks to be
|
||||
// processed, none of the which are originally claimed.
|
||||
SubTasksDone(uint n);
|
||||
|
||||
// Attempt to claim the task "t", returning true if successful,
|
||||
// false if it has already been claimed. The task "t" is required
|
||||
// to be within the range of "this".
|
||||
bool try_claim_task(uint t);
|
||||
|
||||
// The calling thread asserts that it has attempted to claim all the tasks
|
||||
// that it will try to claim. Tasks that are meant to be skipped must be
|
||||
// explicitly passed as extra arguments. Every thread in the parallel task
|
||||
// must execute this.
|
||||
template<typename T0, typename... Ts,
|
||||
ENABLE_IF(Conjunction<std::is_same<T0, Ts>...>::value)>
|
||||
void all_tasks_claimed(T0 first_skipped, Ts... more_skipped) {
|
||||
static_assert(std::is_convertible<T0, uint>::value, "not convertible");
|
||||
uint skipped[] = { static_cast<uint>(first_skipped), static_cast<uint>(more_skipped)... };
|
||||
all_tasks_claimed_impl(skipped, ARRAY_SIZE(skipped));
|
||||
}
|
||||
// if there are no skipped tasks.
|
||||
void all_tasks_claimed() {
|
||||
all_tasks_claimed_impl(nullptr, 0);
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~SubTasksDone();
|
||||
};
|
||||
|
||||
// As above, but for sequential tasks, i.e. instead of claiming
|
||||
// sub-tasks from a set (possibly an enumeration), claim sub-tasks
|
||||
// in sequential order. This is ideal for claiming dynamically
|
||||
// partitioned tasks (like striding in the parallel remembered
|
||||
// set scanning).
|
||||
|
||||
class SequentialSubTasksDone : public CHeapObj<mtInternal> {
|
||||
|
||||
uint _num_tasks; // Total number of tasks available.
|
||||
volatile uint _num_claimed; // Number of tasks claimed.
|
||||
|
||||
NONCOPYABLE(SequentialSubTasksDone);
|
||||
|
||||
public:
|
||||
SequentialSubTasksDone(uint num_tasks) : _num_tasks(num_tasks), _num_claimed(0) { }
|
||||
~SequentialSubTasksDone() {
|
||||
// Claiming may try to claim more tasks than there are.
|
||||
assert(_num_claimed >= _num_tasks, "Claimed %u tasks of %u", _num_claimed, _num_tasks);
|
||||
}
|
||||
|
||||
// Attempt to claim the next unclaimed task in the sequence,
|
||||
// returning true if successful, with t set to the index of the
|
||||
// claimed task. Returns false if there are no more unclaimed tasks
|
||||
// in the sequence. In this case t is undefined.
|
||||
bool try_claim_task(uint& t);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SHARED_WORKERUTILS_HPP
|
@ -1,351 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "gc/shared/gcId.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerManager.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/semaphore.hpp"
|
||||
#include "runtime/thread.inline.hpp"
|
||||
|
||||
// WorkGang dispatcher implemented with semaphores.
|
||||
//
|
||||
// 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 GangTaskDispatcher : public CHeapObj<mtGC> {
|
||||
// The task currently being dispatched to the GangWorkers.
|
||||
AbstractGangTask* _task;
|
||||
|
||||
volatile uint _started;
|
||||
volatile uint _not_finished;
|
||||
|
||||
// Semaphore used to start the GangWorkers.
|
||||
Semaphore* _start_semaphore;
|
||||
// Semaphore used to notify the coordinator that all workers are done.
|
||||
Semaphore* _end_semaphore;
|
||||
|
||||
public:
|
||||
GangTaskDispatcher() :
|
||||
_task(NULL),
|
||||
_started(0),
|
||||
_not_finished(0),
|
||||
_start_semaphore(new Semaphore()),
|
||||
_end_semaphore(new Semaphore())
|
||||
{ }
|
||||
|
||||
~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) {
|
||||
// No workers are allowed to read the state variables until they have been signaled.
|
||||
_task = task;
|
||||
_not_finished = num_workers;
|
||||
|
||||
// Dispatch 'num_workers' number of tasks.
|
||||
_start_semaphore->signal(num_workers);
|
||||
|
||||
// Wait for the last worker to signal the coordinator.
|
||||
_end_semaphore->wait();
|
||||
|
||||
// No workers are allowed to read the state variables after the coordinator has been signaled.
|
||||
assert(_not_finished == 0, "%d not finished workers?", _not_finished);
|
||||
_task = NULL;
|
||||
_started = 0;
|
||||
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
uint num_started = Atomic::add(&_started, 1u);
|
||||
|
||||
// Subtract one to get a zero-indexed worker id.
|
||||
uint worker_id = num_started - 1;
|
||||
|
||||
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.
|
||||
uint not_finished = Atomic::sub(&_not_finished, 1u);
|
||||
|
||||
// The last worker signals to the coordinator that all work is completed.
|
||||
if (not_finished == 0) {
|
||||
_end_semaphore->signal();
|
||||
}
|
||||
}
|
||||
};
|
||||
// Definitions of WorkGang methods.
|
||||
|
||||
WorkGang::WorkGang(const char* name, uint workers) :
|
||||
_workers(NULL),
|
||||
_total_workers(workers),
|
||||
_active_workers(UseDynamicNumberOfGCThreads ? 1U : workers),
|
||||
_created_workers(0),
|
||||
_name(name),
|
||||
_dispatcher(new GangTaskDispatcher())
|
||||
{ }
|
||||
|
||||
WorkGang::~WorkGang() {
|
||||
delete _dispatcher;
|
||||
}
|
||||
|
||||
// The current implementation will exit if the allocation
|
||||
// of any worker fails.
|
||||
void WorkGang::initialize_workers() {
|
||||
log_develop_trace(gc, workgang)("Constructing work gang %s with %u threads", name(), total_workers());
|
||||
_workers = NEW_C_HEAP_ARRAY(GangWorker*, total_workers(), mtInternal);
|
||||
add_workers(true);
|
||||
}
|
||||
|
||||
|
||||
GangWorker* WorkGang::install_worker(uint worker_id) {
|
||||
GangWorker* new_worker = allocate_worker(worker_id);
|
||||
set_thread(worker_id, new_worker);
|
||||
return new_worker;
|
||||
}
|
||||
|
||||
void WorkGang::add_workers(bool initializing) {
|
||||
uint previous_created_workers = _created_workers;
|
||||
|
||||
_created_workers = WorkerManager::add_workers(this,
|
||||
_active_workers,
|
||||
_total_workers,
|
||||
_created_workers,
|
||||
os::gc_thread,
|
||||
initializing);
|
||||
_active_workers = MIN2(_created_workers, _active_workers);
|
||||
|
||||
WorkerManager::log_worker_creation(this, previous_created_workers, _active_workers, _created_workers, initializing);
|
||||
}
|
||||
|
||||
GangWorker* WorkGang::worker(uint i) const {
|
||||
// Array index bounds checking.
|
||||
GangWorker* result = NULL;
|
||||
assert(_workers != NULL, "No workers for indexing");
|
||||
assert(i < total_workers(), "Worker index out of bounds");
|
||||
result = _workers[i];
|
||||
assert(result != NULL, "Indexing to null worker");
|
||||
return result;
|
||||
}
|
||||
|
||||
void WorkGang::threads_do(ThreadClosure* tc) const {
|
||||
assert(tc != NULL, "Null ThreadClosure");
|
||||
uint workers = created_workers();
|
||||
for (uint i = 0; i < workers; i++) {
|
||||
tc->do_thread(worker(i));
|
||||
}
|
||||
}
|
||||
|
||||
GangWorker* WorkGang::allocate_worker(uint worker_id) {
|
||||
return new GangWorker(this, worker_id);
|
||||
}
|
||||
|
||||
void WorkGang::run_task(AbstractGangTask* task) {
|
||||
run_task(task, active_workers());
|
||||
}
|
||||
|
||||
void WorkGang::run_task(AbstractGangTask* task, uint num_workers) {
|
||||
guarantee(num_workers <= total_workers(),
|
||||
"Trying to execute task %s with %u workers which is more than the amount of total workers %u.",
|
||||
task->name(), num_workers, total_workers());
|
||||
guarantee(num_workers > 0, "Trying to execute task %s with zero workers", task->name());
|
||||
uint old_num_workers = _active_workers;
|
||||
update_active_workers(num_workers);
|
||||
_dispatcher->coordinator_execute_on_workers(task, num_workers);
|
||||
update_active_workers(old_num_workers);
|
||||
}
|
||||
|
||||
GangWorker::GangWorker(WorkGang* gang, uint id) {
|
||||
_gang = gang;
|
||||
set_id(id);
|
||||
set_name("%s#%d", gang->name(), id);
|
||||
}
|
||||
|
||||
void GangWorker::run() {
|
||||
initialize();
|
||||
loop();
|
||||
}
|
||||
|
||||
void GangWorker::initialize() {
|
||||
assert(_gang != NULL, "No gang to run in");
|
||||
os::set_priority(this, NearMaxPriority);
|
||||
log_develop_trace(gc, workgang)("Running gang worker for gang %s id %u", gang()->name(), id());
|
||||
assert(!Thread::current()->is_VM_thread(), "VM thread should not be part"
|
||||
" of a work gang");
|
||||
}
|
||||
|
||||
WorkData GangWorker::wait_for_task() {
|
||||
return gang()->dispatcher()->worker_wait_for_task();
|
||||
}
|
||||
|
||||
void GangWorker::signal_task_done() {
|
||||
gang()->dispatcher()->worker_done_with_task();
|
||||
}
|
||||
|
||||
void GangWorker::run_task(WorkData data) {
|
||||
GCIdMark gc_id_mark(data._task->gc_id());
|
||||
log_develop_trace(gc, workgang)("Running work gang: %s task: %s worker: %u", name(), data._task->name(), data._worker_id);
|
||||
|
||||
data._task->work(data._worker_id);
|
||||
|
||||
log_develop_trace(gc, workgang)("Finished work gang: %s task: %s worker: %u thread: " PTR_FORMAT,
|
||||
name(), data._task->name(), data._worker_id, p2i(Thread::current()));
|
||||
}
|
||||
|
||||
void GangWorker::loop() {
|
||||
while (true) {
|
||||
WorkData data = wait_for_task();
|
||||
|
||||
run_task(data);
|
||||
|
||||
signal_task_done();
|
||||
}
|
||||
}
|
||||
|
||||
// *** WorkGangBarrierSync
|
||||
|
||||
WorkGangBarrierSync::WorkGangBarrierSync()
|
||||
: _monitor(Mutex::nosafepoint, "WorkGangBarrierSync_lock"),
|
||||
_n_workers(0), _n_completed(0), _should_reset(false), _aborted(false) {
|
||||
}
|
||||
|
||||
void WorkGangBarrierSync::set_n_workers(uint n_workers) {
|
||||
_n_workers = n_workers;
|
||||
_n_completed = 0;
|
||||
_should_reset = false;
|
||||
_aborted = false;
|
||||
}
|
||||
|
||||
bool WorkGangBarrierSync::enter() {
|
||||
MonitorLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
|
||||
if (should_reset()) {
|
||||
// The should_reset() was set and we are the first worker to enter
|
||||
// the sync barrier. We will zero the n_completed() count which
|
||||
// effectively resets the barrier.
|
||||
zero_completed();
|
||||
set_should_reset(false);
|
||||
}
|
||||
inc_completed();
|
||||
if (n_completed() == n_workers()) {
|
||||
// At this point we would like to reset the barrier to be ready in
|
||||
// case it is used again. However, we cannot set n_completed() to
|
||||
// 0, even after the notify_all(), given that some other workers
|
||||
// might still be waiting for n_completed() to become ==
|
||||
// n_workers(). So, if we set n_completed() to 0, those workers
|
||||
// will get stuck (as they will wake up, see that n_completed() !=
|
||||
// n_workers() and go back to sleep). Instead, we raise the
|
||||
// should_reset() flag and the barrier will be reset the first
|
||||
// time a worker enters it again.
|
||||
set_should_reset(true);
|
||||
ml.notify_all();
|
||||
} else {
|
||||
while (n_completed() != n_workers() && !aborted()) {
|
||||
ml.wait();
|
||||
}
|
||||
}
|
||||
return !aborted();
|
||||
}
|
||||
|
||||
void WorkGangBarrierSync::abort() {
|
||||
MutexLocker x(monitor(), Mutex::_no_safepoint_check_flag);
|
||||
set_aborted();
|
||||
monitor()->notify_all();
|
||||
}
|
||||
|
||||
// SubTasksDone functions.
|
||||
|
||||
SubTasksDone::SubTasksDone(uint n) :
|
||||
_tasks(NULL), _n_tasks(n) {
|
||||
_tasks = NEW_C_HEAP_ARRAY(bool, n, mtInternal);
|
||||
for (uint i = 0; i < _n_tasks; i++) {
|
||||
_tasks[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ASSERT
|
||||
void SubTasksDone::all_tasks_claimed_impl(uint skipped[], size_t skipped_size) {
|
||||
if (Atomic::cmpxchg(&_verification_done, false, true)) {
|
||||
// another thread has done the verification
|
||||
return;
|
||||
}
|
||||
// all non-skipped tasks are claimed
|
||||
for (uint i = 0; i < _n_tasks; ++i) {
|
||||
if (!_tasks[i]) {
|
||||
auto is_skipped = false;
|
||||
for (size_t j = 0; j < skipped_size; ++j) {
|
||||
if (i == skipped[j]) {
|
||||
is_skipped = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(is_skipped, "%d not claimed.", i);
|
||||
}
|
||||
}
|
||||
// all skipped tasks are *not* claimed
|
||||
for (size_t i = 0; i < skipped_size; ++i) {
|
||||
auto task_index = skipped[i];
|
||||
assert(task_index < _n_tasks, "Array in range.");
|
||||
assert(!_tasks[task_index], "%d is both claimed and skipped.", task_index);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool SubTasksDone::try_claim_task(uint t) {
|
||||
assert(t < _n_tasks, "bad task id.");
|
||||
return !_tasks[t] && !Atomic::cmpxchg(&_tasks[t], false, true);
|
||||
}
|
||||
|
||||
SubTasksDone::~SubTasksDone() {
|
||||
assert(_verification_done, "all_tasks_claimed must have been called.");
|
||||
FREE_C_HEAP_ARRAY(bool, _tasks);
|
||||
}
|
||||
|
||||
// *** SequentialSubTasksDone
|
||||
|
||||
bool SequentialSubTasksDone::try_claim_task(uint& t) {
|
||||
t = _num_claimed;
|
||||
if (t < _num_tasks) {
|
||||
t = Atomic::add(&_num_claimed, 1u) - 1;
|
||||
}
|
||||
return t < _num_tasks;
|
||||
}
|
@ -1,328 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_GC_SHARED_WORKGROUP_HPP
|
||||
#define SHARE_GC_SHARED_WORKGROUP_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "metaprogramming/enableIf.hpp"
|
||||
#include "metaprogramming/logical.hpp"
|
||||
#include "runtime/globals.hpp"
|
||||
#include "runtime/nonJavaThread.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
#include "gc/shared/gcId.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "utilities/debug.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
// Task class hierarchy:
|
||||
// AbstractGangTask
|
||||
//
|
||||
// Gang/Group class hierarchy:
|
||||
// WorkGang
|
||||
//
|
||||
// Worker class hierarchy:
|
||||
// GangWorker (subclass of WorkerThread)
|
||||
|
||||
// Forward declarations of classes defined here
|
||||
|
||||
class GangWorker;
|
||||
class Semaphore;
|
||||
class ThreadClosure;
|
||||
class GangTaskDispatcher;
|
||||
|
||||
// An abstract task to be worked on by a gang.
|
||||
// You subclass this to supply your own work() method
|
||||
class AbstractGangTask : public CHeapObj<mtInternal> {
|
||||
const char* _name;
|
||||
const uint _gc_id;
|
||||
|
||||
public:
|
||||
explicit AbstractGangTask(const char* name) :
|
||||
_name(name),
|
||||
_gc_id(GCId::current_or_undefined())
|
||||
{}
|
||||
|
||||
// The abstract work method.
|
||||
// The argument tells you which member of the gang you are.
|
||||
virtual void work(uint worker_id) = 0;
|
||||
|
||||
// Debugging accessor for the name.
|
||||
const char* name() const { return _name; }
|
||||
const uint gc_id() const { return _gc_id; }
|
||||
};
|
||||
|
||||
struct WorkData {
|
||||
AbstractGangTask* _task;
|
||||
uint _worker_id;
|
||||
WorkData(AbstractGangTask* task, uint worker_id) : _task(task), _worker_id(worker_id) {}
|
||||
};
|
||||
|
||||
// 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 workers.
|
||||
class WorkGang : public CHeapObj<mtInternal> {
|
||||
// The array of worker threads for this gang.
|
||||
GangWorker** _workers;
|
||||
// The count of the number of workers in the gang.
|
||||
uint _total_workers;
|
||||
// The currently active workers in this gang.
|
||||
uint _active_workers;
|
||||
// The count of created workers in the gang.
|
||||
uint _created_workers;
|
||||
// Printing support.
|
||||
const char* _name;
|
||||
|
||||
// To get access to the GangTaskDispatcher instance.
|
||||
friend class GangWorker;
|
||||
GangTaskDispatcher* const _dispatcher;
|
||||
|
||||
GangTaskDispatcher* dispatcher() const { return _dispatcher; }
|
||||
|
||||
void set_thread(uint worker_id, GangWorker* worker) {
|
||||
_workers[worker_id] = worker;
|
||||
}
|
||||
|
||||
// Add GC workers when _created_workers < _active_workers; otherwise, no-op.
|
||||
// If there's no memory/thread allocation failure, _created_worker is
|
||||
// adjusted to match _active_workers (_created_worker == _active_workers).
|
||||
void add_workers(bool initializing);
|
||||
|
||||
GangWorker* allocate_worker(uint which);
|
||||
|
||||
public:
|
||||
WorkGang(const char* name, uint workers);
|
||||
|
||||
~WorkGang();
|
||||
|
||||
// Initialize workers in the gang. Return true if initialization succeeded.
|
||||
void initialize_workers();
|
||||
|
||||
uint total_workers() const { return _total_workers; }
|
||||
|
||||
uint created_workers() const {
|
||||
return _created_workers;
|
||||
}
|
||||
|
||||
uint active_workers() const {
|
||||
assert(_active_workers != 0, "zero active workers");
|
||||
assert(_active_workers <= _total_workers,
|
||||
"_active_workers: %u > _total_workers: %u", _active_workers, _total_workers);
|
||||
return _active_workers;
|
||||
}
|
||||
|
||||
uint update_active_workers(uint v) {
|
||||
assert(v <= _total_workers,
|
||||
"Trying to set more workers active than there are");
|
||||
assert(v != 0, "Trying to set active workers to 0");
|
||||
_active_workers = v;
|
||||
add_workers(false /* initializing */);
|
||||
log_trace(gc, task)("%s: using %d out of %d workers", name(), _active_workers, _total_workers);
|
||||
return _active_workers;
|
||||
}
|
||||
|
||||
// Return the Ith worker.
|
||||
GangWorker* worker(uint i) const;
|
||||
|
||||
// Base name (without worker id #) of threads.
|
||||
const char* group_name() { return name(); }
|
||||
|
||||
void threads_do(ThreadClosure* tc) const;
|
||||
|
||||
// Create a GC worker and install it into the work gang.
|
||||
virtual GangWorker* install_worker(uint which);
|
||||
|
||||
// Debugging.
|
||||
const char* name() const { return _name; }
|
||||
|
||||
// Run a task using the current active number of workers, returns when the task is done.
|
||||
void run_task(AbstractGangTask* task);
|
||||
|
||||
// Run a task with the given number of workers, returns
|
||||
// when the task is done. The number of workers must be at most the number of
|
||||
// active workers. Additional workers may be created if an insufficient
|
||||
// number currently exists.
|
||||
void run_task(AbstractGangTask* task, uint num_workers);
|
||||
};
|
||||
|
||||
// Temporarily try to set the number of active workers.
|
||||
// It's not guaranteed that it succeeds, and users need to
|
||||
// query the number of active workers.
|
||||
class WithUpdatedActiveWorkers : public StackObj {
|
||||
private:
|
||||
WorkGang* const _gang;
|
||||
const uint _old_active_workers;
|
||||
|
||||
public:
|
||||
WithUpdatedActiveWorkers(WorkGang* gang, uint requested_num_workers) :
|
||||
_gang(gang),
|
||||
_old_active_workers(gang->active_workers()) {
|
||||
uint capped_num_workers = MIN2(requested_num_workers, gang->total_workers());
|
||||
gang->update_active_workers(capped_num_workers);
|
||||
}
|
||||
|
||||
~WithUpdatedActiveWorkers() {
|
||||
_gang->update_active_workers(_old_active_workers);
|
||||
}
|
||||
};
|
||||
|
||||
// Several instances of this class run in parallel as workers for a gang.
|
||||
class GangWorker: public WorkerThread {
|
||||
private:
|
||||
WorkGang* _gang;
|
||||
|
||||
void initialize();
|
||||
void loop();
|
||||
|
||||
WorkGang* gang() const { return _gang; }
|
||||
|
||||
WorkData wait_for_task();
|
||||
void run_task(WorkData work);
|
||||
void signal_task_done();
|
||||
|
||||
protected:
|
||||
// The only real method: run a task for the gang.
|
||||
void run() override;
|
||||
|
||||
public:
|
||||
GangWorker(WorkGang* gang, uint id);
|
||||
|
||||
// Printing
|
||||
const char* type_name() const override { return "GCTaskThread"; }
|
||||
};
|
||||
|
||||
// A class that acts as a synchronisation barrier. Workers enter
|
||||
// the barrier and must wait until all other workers have entered
|
||||
// before any of them may leave.
|
||||
|
||||
class WorkGangBarrierSync : public StackObj {
|
||||
protected:
|
||||
Monitor _monitor;
|
||||
uint _n_workers;
|
||||
uint _n_completed;
|
||||
bool _should_reset;
|
||||
bool _aborted;
|
||||
|
||||
Monitor* monitor() { return &_monitor; }
|
||||
uint n_workers() { return _n_workers; }
|
||||
uint n_completed() { return _n_completed; }
|
||||
bool should_reset() { return _should_reset; }
|
||||
bool aborted() { return _aborted; }
|
||||
|
||||
void zero_completed() { _n_completed = 0; }
|
||||
void inc_completed() { _n_completed++; }
|
||||
void set_aborted() { _aborted = true; }
|
||||
void set_should_reset(bool v) { _should_reset = v; }
|
||||
|
||||
public:
|
||||
WorkGangBarrierSync();
|
||||
|
||||
// Set the number of workers that will use the barrier.
|
||||
// Must be called before any of the workers start running.
|
||||
void set_n_workers(uint n_workers);
|
||||
|
||||
// Enter the barrier. A worker that enters the barrier will
|
||||
// not be allowed to leave until all other threads have
|
||||
// also entered the barrier or the barrier is aborted.
|
||||
// Returns false if the barrier was aborted.
|
||||
bool enter();
|
||||
|
||||
// Aborts the barrier and wakes up any threads waiting for
|
||||
// the barrier to complete. The barrier will remain in the
|
||||
// aborted state until the next call to set_n_workers().
|
||||
void abort();
|
||||
};
|
||||
|
||||
// A class to manage claiming of subtasks within a group of tasks. The
|
||||
// subtasks will be identified by integer indices, usually elements of an
|
||||
// enumeration type.
|
||||
|
||||
class SubTasksDone: public CHeapObj<mtInternal> {
|
||||
volatile bool* _tasks;
|
||||
uint _n_tasks;
|
||||
|
||||
// make sure verification logic is run exactly once to avoid duplicate assertion failures
|
||||
DEBUG_ONLY(volatile bool _verification_done = false;)
|
||||
void all_tasks_claimed_impl(uint skipped[], size_t skipped_size) NOT_DEBUG_RETURN;
|
||||
|
||||
NONCOPYABLE(SubTasksDone);
|
||||
|
||||
public:
|
||||
// Initializes "this" to a state in which there are "n" tasks to be
|
||||
// processed, none of the which are originally claimed.
|
||||
SubTasksDone(uint n);
|
||||
|
||||
// Attempt to claim the task "t", returning true if successful,
|
||||
// false if it has already been claimed. The task "t" is required
|
||||
// to be within the range of "this".
|
||||
bool try_claim_task(uint t);
|
||||
|
||||
// The calling thread asserts that it has attempted to claim all the tasks
|
||||
// that it will try to claim. Tasks that are meant to be skipped must be
|
||||
// explicitly passed as extra arguments. Every thread in the parallel task
|
||||
// must execute this.
|
||||
template<typename T0, typename... Ts,
|
||||
ENABLE_IF(Conjunction<std::is_same<T0, Ts>...>::value)>
|
||||
void all_tasks_claimed(T0 first_skipped, Ts... more_skipped) {
|
||||
static_assert(std::is_convertible<T0, uint>::value, "not convertible");
|
||||
uint skipped[] = { static_cast<uint>(first_skipped), static_cast<uint>(more_skipped)... };
|
||||
all_tasks_claimed_impl(skipped, ARRAY_SIZE(skipped));
|
||||
}
|
||||
// if there are no skipped tasks.
|
||||
void all_tasks_claimed() {
|
||||
all_tasks_claimed_impl(nullptr, 0);
|
||||
}
|
||||
|
||||
// Destructor.
|
||||
~SubTasksDone();
|
||||
};
|
||||
|
||||
// As above, but for sequential tasks, i.e. instead of claiming
|
||||
// sub-tasks from a set (possibly an enumeration), claim sub-tasks
|
||||
// in sequential order. This is ideal for claiming dynamically
|
||||
// partitioned tasks (like striding in the parallel remembered
|
||||
// set scanning).
|
||||
|
||||
class SequentialSubTasksDone : public CHeapObj<mtInternal> {
|
||||
|
||||
uint _num_tasks; // Total number of tasks available.
|
||||
volatile uint _num_claimed; // Number of tasks claimed.
|
||||
|
||||
NONCOPYABLE(SequentialSubTasksDone);
|
||||
|
||||
public:
|
||||
SequentialSubTasksDone(uint num_tasks) : _num_tasks(num_tasks), _num_claimed(0) { }
|
||||
~SequentialSubTasksDone() {
|
||||
// Claiming may try to claim more tasks than there are.
|
||||
assert(_num_claimed >= _num_tasks, "Claimed %u tasks of %u", _num_claimed, _num_tasks);
|
||||
}
|
||||
|
||||
// Attempt to claim the next unclaimed task in the sequence,
|
||||
// returning true if successful, with t set to the index of the
|
||||
// claimed task. Returns false if there are no more unclaimed tasks
|
||||
// in the sequence. In this case t is undefined.
|
||||
bool try_claim_task(uint& t);
|
||||
};
|
||||
|
||||
#endif // SHARE_GC_SHARED_WORKGROUP_HPP
|
@ -153,14 +153,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahDisarmNMethodsTask : public AbstractGangTask {
|
||||
class ShenandoahDisarmNMethodsTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahDisarmNMethodClosure _cl;
|
||||
ShenandoahConcurrentNMethodIterator _iterator;
|
||||
|
||||
public:
|
||||
ShenandoahDisarmNMethodsTask() :
|
||||
AbstractGangTask("Shenandoah Disarm NMethods"),
|
||||
WorkerTask("Shenandoah Disarm NMethods"),
|
||||
_iterator(ShenandoahCodeRoots::table()) {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "Only at a safepoint");
|
||||
MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
@ -258,7 +258,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahUnlinkTask : public AbstractGangTask {
|
||||
class ShenandoahUnlinkTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahNMethodUnlinkClosure _cl;
|
||||
ICRefillVerifier* _verifier;
|
||||
@ -266,7 +266,7 @@ private:
|
||||
|
||||
public:
|
||||
ShenandoahUnlinkTask(bool unloading_occurred, ICRefillVerifier* verifier) :
|
||||
AbstractGangTask("Shenandoah Unlink NMethods"),
|
||||
WorkerTask("Shenandoah Unlink NMethods"),
|
||||
_cl(unloading_occurred),
|
||||
_verifier(verifier),
|
||||
_iterator(ShenandoahCodeRoots::table()) {
|
||||
@ -289,7 +289,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void ShenandoahCodeRoots::unlink(WorkGang* workers, bool unloading_occurred) {
|
||||
void ShenandoahCodeRoots::unlink(WorkerThreads* workers, bool unloading_occurred) {
|
||||
assert(ShenandoahHeap::heap()->unload_classes(), "Only when running concurrent class unloading");
|
||||
|
||||
for (;;) {
|
||||
@ -320,14 +320,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahNMethodPurgeTask : public AbstractGangTask {
|
||||
class ShenandoahNMethodPurgeTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahNMethodPurgeClosure _cl;
|
||||
ShenandoahConcurrentNMethodIterator _iterator;
|
||||
|
||||
public:
|
||||
ShenandoahNMethodPurgeTask() :
|
||||
AbstractGangTask("Shenandoah Purge NMethods"),
|
||||
WorkerTask("Shenandoah Purge NMethods"),
|
||||
_cl(),
|
||||
_iterator(ShenandoahCodeRoots::table()) {
|
||||
MutexLocker mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
|
||||
@ -344,7 +344,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void ShenandoahCodeRoots::purge(WorkGang* workers) {
|
||||
void ShenandoahCodeRoots::purge(WorkerThreads* workers) {
|
||||
assert(ShenandoahHeap::heap()->unload_classes(), "Only when running concurrent class unloading");
|
||||
|
||||
ShenandoahNMethodPurgeTask task;
|
||||
|
@ -37,7 +37,7 @@ class ShenandoahHeap;
|
||||
class ShenandoahHeapRegion;
|
||||
class ShenandoahNMethodTable;
|
||||
class ShenandoahNMethodTableSnapshot;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
class ShenandoahParallelCodeHeapIterator {
|
||||
friend class CodeCache;
|
||||
@ -95,8 +95,8 @@ public:
|
||||
}
|
||||
|
||||
// Concurrent nmethod unloading support
|
||||
static void unlink(WorkGang* workers, bool unloading_occurred);
|
||||
static void purge(WorkGang* workers);
|
||||
static void unlink(WorkerThreads* workers, bool unloading_occurred);
|
||||
static void purge(WorkerThreads* workers);
|
||||
static void arm_nmethods();
|
||||
static void disarm_nmethods();
|
||||
static int disarmed_value() { return _disarmed_value; }
|
||||
|
@ -635,13 +635,13 @@ void ShenandoahConcurrentEvacThreadClosure::do_thread(Thread* thread) {
|
||||
StackWatermarkSet::finish_processing(jt, _oops, StackWatermarkKind::gc);
|
||||
}
|
||||
|
||||
class ShenandoahConcurrentEvacUpdateThreadTask : public AbstractGangTask {
|
||||
class ShenandoahConcurrentEvacUpdateThreadTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahJavaThreadsIterator _java_threads;
|
||||
|
||||
public:
|
||||
ShenandoahConcurrentEvacUpdateThreadTask(uint n_workers) :
|
||||
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Thread Roots"),
|
||||
WorkerTask("Shenandoah Evacuate/Update Concurrent Thread Roots"),
|
||||
_java_threads(ShenandoahPhaseTimings::conc_thread_roots, n_workers) {
|
||||
}
|
||||
|
||||
@ -732,7 +732,7 @@ public:
|
||||
|
||||
// This task not only evacuates/updates marked weak roots, but also "NULL"
|
||||
// dead weak roots.
|
||||
class ShenandoahConcurrentWeakRootsEvacUpdateTask : public AbstractGangTask {
|
||||
class ShenandoahConcurrentWeakRootsEvacUpdateTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahVMWeakRoots<true /*concurrent*/> _vm_roots;
|
||||
|
||||
@ -744,7 +744,7 @@ private:
|
||||
|
||||
public:
|
||||
ShenandoahConcurrentWeakRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
|
||||
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Weak Roots"),
|
||||
WorkerTask("Shenandoah Evacuate/Update Concurrent Weak Roots"),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
|
||||
_nmethod_itr(ShenandoahCodeRoots::table()),
|
||||
@ -846,7 +846,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahConcurrentRootsEvacUpdateTask : public AbstractGangTask {
|
||||
class ShenandoahConcurrentRootsEvacUpdateTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahPhaseTimings::Phase _phase;
|
||||
ShenandoahVMRoots<true /*concurrent*/> _vm_roots;
|
||||
@ -856,7 +856,7 @@ private:
|
||||
|
||||
public:
|
||||
ShenandoahConcurrentRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) :
|
||||
AbstractGangTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
|
||||
WorkerTask("Shenandoah Evacuate/Update Concurrent Strong Roots"),
|
||||
_phase(phase),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/),
|
||||
|
@ -42,14 +42,14 @@
|
||||
#include "memory/iterator.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
|
||||
class ShenandoahConcurrentMarkingTask : public AbstractGangTask {
|
||||
class ShenandoahConcurrentMarkingTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahConcurrentMark* const _cm;
|
||||
TaskTerminator* const _terminator;
|
||||
|
||||
public:
|
||||
ShenandoahConcurrentMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator) :
|
||||
AbstractGangTask("Shenandoah Concurrent Mark"), _cm(cm), _terminator(terminator) {
|
||||
WorkerTask("Shenandoah Concurrent Mark"), _cm(cm), _terminator(terminator) {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
@ -93,7 +93,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahFinalMarkingTask : public AbstractGangTask {
|
||||
class ShenandoahFinalMarkingTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahConcurrentMark* _cm;
|
||||
TaskTerminator* _terminator;
|
||||
@ -101,7 +101,7 @@ private:
|
||||
|
||||
public:
|
||||
ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) :
|
||||
AbstractGangTask("Shenandoah Final Mark"), _cm(cm), _terminator(terminator), _dedup_string(dedup_string) {
|
||||
WorkerTask("Shenandoah Final Mark"), _cm(cm), _terminator(terminator), _dedup_string(dedup_string) {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
@ -137,7 +137,7 @@ ShenandoahConcurrentMark::ShenandoahConcurrentMark() :
|
||||
ShenandoahMark() {}
|
||||
|
||||
// Mark concurrent roots during concurrent phases
|
||||
class ShenandoahMarkConcurrentRootsTask : public AbstractGangTask {
|
||||
class ShenandoahMarkConcurrentRootsTask : public WorkerTask {
|
||||
private:
|
||||
SuspendibleThreadSetJoiner _sts_joiner;
|
||||
ShenandoahConcurrentRootScanner _root_scanner;
|
||||
@ -156,7 +156,7 @@ ShenandoahMarkConcurrentRootsTask::ShenandoahMarkConcurrentRootsTask(ShenandoahO
|
||||
ShenandoahReferenceProcessor* rp,
|
||||
ShenandoahPhaseTimings::Phase phase,
|
||||
uint nworkers) :
|
||||
AbstractGangTask("Shenandoah Concurrent Mark Roots"),
|
||||
WorkerTask("Shenandoah Concurrent Mark Roots"),
|
||||
_root_scanner(nworkers, phase),
|
||||
_queue_set(qs),
|
||||
_rp(rp) {
|
||||
@ -176,7 +176,7 @@ void ShenandoahConcurrentMark::mark_concurrent_roots() {
|
||||
|
||||
TASKQUEUE_STATS_ONLY(task_queues()->reset_taskqueue_stats());
|
||||
|
||||
WorkGang* workers = heap->workers();
|
||||
WorkerThreads* workers = heap->workers();
|
||||
ShenandoahReferenceProcessor* rp = heap->ref_processor();
|
||||
task_queues()->reserve(workers->active_workers());
|
||||
ShenandoahMarkConcurrentRootsTask task(task_queues(), rp, ShenandoahPhaseTimings::conc_mark_roots, workers->active_workers());
|
||||
@ -199,7 +199,7 @@ public:
|
||||
|
||||
void ShenandoahConcurrentMark::concurrent_mark() {
|
||||
ShenandoahHeap* const heap = ShenandoahHeap::heap();
|
||||
WorkGang* workers = heap->workers();
|
||||
WorkerThreads* workers = heap->workers();
|
||||
uint nworkers = workers->active_workers();
|
||||
task_queues()->reserve(nworkers);
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "gc/shared/gcTraceTime.inline.hpp"
|
||||
#include "gc/shared/preservedMarks.inline.hpp"
|
||||
#include "gc/shared/tlab_globals.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shenandoah/heuristics/shenandoahHeuristics.hpp"
|
||||
#include "gc/shenandoah/shenandoahConcurrentGC.hpp"
|
||||
#include "gc/shenandoah/shenandoahCollectionSet.hpp"
|
||||
@ -59,7 +60,6 @@
|
||||
#include "utilities/copy.hpp"
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
|
||||
ShenandoahFullGC::ShenandoahFullGC() :
|
||||
_gc_timer(ShenandoahHeap::heap()->gc_timer()),
|
||||
@ -363,7 +363,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahPrepareForCompactionTask : public AbstractGangTask {
|
||||
class ShenandoahPrepareForCompactionTask : public WorkerTask {
|
||||
private:
|
||||
PreservedMarksSet* const _preserved_marks;
|
||||
ShenandoahHeap* const _heap;
|
||||
@ -371,7 +371,7 @@ private:
|
||||
|
||||
public:
|
||||
ShenandoahPrepareForCompactionTask(PreservedMarksSet *preserved_marks, ShenandoahHeapRegionSet **worker_slices) :
|
||||
AbstractGangTask("Shenandoah Prepare For Compaction"),
|
||||
WorkerTask("Shenandoah Prepare For Compaction"),
|
||||
_preserved_marks(preserved_marks),
|
||||
_heap(ShenandoahHeap::heap()), _worker_slices(worker_slices) {
|
||||
}
|
||||
@ -757,14 +757,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahAdjustPointersTask : public AbstractGangTask {
|
||||
class ShenandoahAdjustPointersTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahHeap* const _heap;
|
||||
ShenandoahRegionIterator _regions;
|
||||
|
||||
public:
|
||||
ShenandoahAdjustPointersTask() :
|
||||
AbstractGangTask("Shenandoah Adjust Pointers"),
|
||||
WorkerTask("Shenandoah Adjust Pointers"),
|
||||
_heap(ShenandoahHeap::heap()) {
|
||||
}
|
||||
|
||||
@ -781,13 +781,13 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahAdjustRootPointersTask : public AbstractGangTask {
|
||||
class ShenandoahAdjustRootPointersTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahRootAdjuster* _rp;
|
||||
PreservedMarksSet* _preserved_marks;
|
||||
public:
|
||||
ShenandoahAdjustRootPointersTask(ShenandoahRootAdjuster* rp, PreservedMarksSet* preserved_marks) :
|
||||
AbstractGangTask("Shenandoah Adjust Root Pointers"),
|
||||
WorkerTask("Shenandoah Adjust Root Pointers"),
|
||||
_rp(rp),
|
||||
_preserved_marks(preserved_marks) {}
|
||||
|
||||
@ -805,7 +805,7 @@ void ShenandoahFullGC::phase3_update_references() {
|
||||
|
||||
ShenandoahHeap* heap = ShenandoahHeap::heap();
|
||||
|
||||
WorkGang* workers = heap->workers();
|
||||
WorkerThreads* workers = heap->workers();
|
||||
uint nworkers = workers->active_workers();
|
||||
{
|
||||
#if COMPILER2_OR_JVMCI
|
||||
@ -845,14 +845,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahCompactObjectsTask : public AbstractGangTask {
|
||||
class ShenandoahCompactObjectsTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahHeap* const _heap;
|
||||
ShenandoahHeapRegionSet** const _worker_slices;
|
||||
|
||||
public:
|
||||
ShenandoahCompactObjectsTask(ShenandoahHeapRegionSet** worker_slices) :
|
||||
AbstractGangTask("Shenandoah Compact Objects"),
|
||||
WorkerTask("Shenandoah Compact Objects"),
|
||||
_heap(ShenandoahHeap::heap()),
|
||||
_worker_slices(worker_slices) {
|
||||
}
|
||||
@ -995,13 +995,13 @@ void ShenandoahFullGC::compact_humongous_objects() {
|
||||
// cannot be iterated over using oop->size(). The only way to safely iterate over those is using
|
||||
// a valid marking bitmap and valid TAMS pointer. This class only resets marking
|
||||
// bitmaps for un-pinned regions, and later we only reset TAMS for unpinned regions.
|
||||
class ShenandoahMCResetCompleteBitmapTask : public AbstractGangTask {
|
||||
class ShenandoahMCResetCompleteBitmapTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahRegionIterator _regions;
|
||||
|
||||
public:
|
||||
ShenandoahMCResetCompleteBitmapTask() :
|
||||
AbstractGangTask("Shenandoah Reset Bitmap") {
|
||||
WorkerTask("Shenandoah Reset Bitmap") {
|
||||
}
|
||||
|
||||
void work(uint worker_id) {
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shenandoah/shenandoahClosures.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahGC.hpp"
|
||||
#include "gc/shenandoah/shenandoahHeap.hpp"
|
||||
@ -51,13 +51,13 @@ const char* ShenandoahGC::degen_point_to_string(ShenandoahDegenPoint point) {
|
||||
}
|
||||
}
|
||||
|
||||
class ShenandoahUpdateRootsTask : public AbstractGangTask {
|
||||
class ShenandoahUpdateRootsTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahRootUpdater* _root_updater;
|
||||
bool _check_alive;
|
||||
public:
|
||||
ShenandoahUpdateRootsTask(ShenandoahRootUpdater* root_updater, bool check_alive) :
|
||||
AbstractGangTask("Shenandoah Update Roots"),
|
||||
WorkerTask("Shenandoah Update Roots"),
|
||||
_root_updater(root_updater),
|
||||
_check_alive(check_alive){
|
||||
}
|
||||
@ -95,7 +95,7 @@ void ShenandoahGC::update_roots(bool full_gc) {
|
||||
#endif
|
||||
|
||||
ShenandoahHeap* const heap = ShenandoahHeap::heap();
|
||||
WorkGang* workers = heap->workers();
|
||||
WorkerThreads* workers = heap->workers();
|
||||
uint nworkers = workers->active_workers();
|
||||
|
||||
ShenandoahRootUpdater root_updater(nworkers, p);
|
||||
|
@ -88,13 +88,13 @@
|
||||
#include "utilities/events.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
|
||||
class ShenandoahPretouchHeapTask : public AbstractGangTask {
|
||||
class ShenandoahPretouchHeapTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahRegionIterator _regions;
|
||||
const size_t _page_size;
|
||||
public:
|
||||
ShenandoahPretouchHeapTask(size_t page_size) :
|
||||
AbstractGangTask("Shenandoah Pretouch Heap"),
|
||||
WorkerTask("Shenandoah Pretouch Heap"),
|
||||
_page_size(page_size) {}
|
||||
|
||||
virtual void work(uint worker_id) {
|
||||
@ -108,7 +108,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahPretouchBitmapTask : public AbstractGangTask {
|
||||
class ShenandoahPretouchBitmapTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahRegionIterator _regions;
|
||||
char* _bitmap_base;
|
||||
@ -116,7 +116,7 @@ private:
|
||||
const size_t _page_size;
|
||||
public:
|
||||
ShenandoahPretouchBitmapTask(char* bitmap_base, size_t bitmap_size, size_t page_size) :
|
||||
AbstractGangTask("Shenandoah Pretouch Bitmap"),
|
||||
WorkerTask("Shenandoah Pretouch Bitmap"),
|
||||
_bitmap_base(bitmap_base),
|
||||
_bitmap_size(bitmap_size),
|
||||
_page_size(page_size) {}
|
||||
@ -495,7 +495,7 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
|
||||
BarrierSet::set_barrier_set(new ShenandoahBarrierSet(this));
|
||||
|
||||
_max_workers = MAX2(_max_workers, 1U);
|
||||
_workers = new ShenandoahWorkGang("Shenandoah GC Threads", _max_workers);
|
||||
_workers = new ShenandoahWorkerThreads("Shenandoah GC Threads", _max_workers);
|
||||
if (_workers == NULL) {
|
||||
vm_exit_during_initialization("Failed necessary allocation.");
|
||||
} else {
|
||||
@ -503,7 +503,7 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
|
||||
}
|
||||
|
||||
if (ParallelGCThreads > 1) {
|
||||
_safepoint_workers = new ShenandoahWorkGang("Safepoint Cleanup Thread",
|
||||
_safepoint_workers = new ShenandoahWorkerThreads("Safepoint Cleanup Thread",
|
||||
ParallelGCThreads);
|
||||
_safepoint_workers->initialize_workers();
|
||||
}
|
||||
@ -513,13 +513,13 @@ ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) :
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
class ShenandoahResetBitmapTask : public AbstractGangTask {
|
||||
class ShenandoahResetBitmapTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahRegionIterator _regions;
|
||||
|
||||
public:
|
||||
ShenandoahResetBitmapTask() :
|
||||
AbstractGangTask("Shenandoah Reset Bitmap") {}
|
||||
WorkerTask("Shenandoah Reset Bitmap") {}
|
||||
|
||||
void work(uint worker_id) {
|
||||
ShenandoahHeapRegion* region = _regions.next();
|
||||
@ -612,7 +612,7 @@ void ShenandoahHeap::post_initialize() {
|
||||
_workers->threads_do(&init_gclabs);
|
||||
|
||||
// gclab can not be initialized early during VM startup, as it can not determinate its max_size.
|
||||
// Now, we will let WorkGang to initialize gclab when new worker is created.
|
||||
// Now, we will let WorkerThreads to initialize gclab when new worker is created.
|
||||
_workers->set_initialize_gclab();
|
||||
if (_safepoint_workers != NULL) {
|
||||
_safepoint_workers->threads_do(&init_gclabs);
|
||||
@ -953,7 +953,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahEvacuationTask : public AbstractGangTask {
|
||||
class ShenandoahEvacuationTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahHeap* const _sh;
|
||||
ShenandoahCollectionSet* const _cs;
|
||||
@ -962,7 +962,7 @@ public:
|
||||
ShenandoahEvacuationTask(ShenandoahHeap* sh,
|
||||
ShenandoahCollectionSet* cs,
|
||||
bool concurrent) :
|
||||
AbstractGangTask("Shenandoah Evacuation"),
|
||||
WorkerTask("Shenandoah Evacuation"),
|
||||
_sh(sh),
|
||||
_cs(cs),
|
||||
_concurrent(concurrent)
|
||||
@ -1483,7 +1483,7 @@ void ShenandoahHeap::heap_region_iterate(ShenandoahHeapRegionClosure* blk) const
|
||||
}
|
||||
}
|
||||
|
||||
class ShenandoahParallelHeapRegionTask : public AbstractGangTask {
|
||||
class ShenandoahParallelHeapRegionTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahHeap* const _heap;
|
||||
ShenandoahHeapRegionClosure* const _blk;
|
||||
@ -1494,7 +1494,7 @@ private:
|
||||
|
||||
public:
|
||||
ShenandoahParallelHeapRegionTask(ShenandoahHeapRegionClosure* blk) :
|
||||
AbstractGangTask("Shenandoah Parallel Region Operation"),
|
||||
WorkerTask("Shenandoah Parallel Region Operation"),
|
||||
_heap(ShenandoahHeap::heap()), _blk(blk), _index(0) {}
|
||||
|
||||
void work(uint worker_id) {
|
||||
@ -2010,13 +2010,13 @@ ShenandoahVerifier* ShenandoahHeap::verifier() {
|
||||
}
|
||||
|
||||
template<bool CONCURRENT>
|
||||
class ShenandoahUpdateHeapRefsTask : public AbstractGangTask {
|
||||
class ShenandoahUpdateHeapRefsTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahHeap* _heap;
|
||||
ShenandoahRegionIterator* _regions;
|
||||
public:
|
||||
ShenandoahUpdateHeapRefsTask(ShenandoahRegionIterator* regions) :
|
||||
AbstractGangTask("Shenandoah Update References"),
|
||||
WorkerTask("Shenandoah Update References"),
|
||||
_heap(ShenandoahHeap::heap()),
|
||||
_regions(regions) {
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ class ShenandoahMonitoringSupport;
|
||||
class ShenandoahPacer;
|
||||
class ShenandoahReferenceProcessor;
|
||||
class ShenandoahVerifier;
|
||||
class ShenandoahWorkGang;
|
||||
class ShenandoahWorkerThreads;
|
||||
class VMStructs;
|
||||
|
||||
// Used for buffering per-region liveness data.
|
||||
@ -207,15 +207,15 @@ public:
|
||||
//
|
||||
private:
|
||||
uint _max_workers;
|
||||
ShenandoahWorkGang* _workers;
|
||||
ShenandoahWorkGang* _safepoint_workers;
|
||||
ShenandoahWorkerThreads* _workers;
|
||||
ShenandoahWorkerThreads* _safepoint_workers;
|
||||
|
||||
public:
|
||||
uint max_workers();
|
||||
void assert_gc_workers(uint nworker) NOT_DEBUG_RETURN;
|
||||
|
||||
WorkGang* workers() const;
|
||||
WorkGang* safepoint_workers();
|
||||
WorkerThreads* workers() const;
|
||||
WorkerThreads* safepoint_workers();
|
||||
|
||||
void gc_threads_do(ThreadClosure* tcl) const;
|
||||
|
||||
|
@ -64,11 +64,11 @@ inline bool ShenandoahHeap::has_forwarded_objects() const {
|
||||
return _gc_state.is_set(HAS_FORWARDED);
|
||||
}
|
||||
|
||||
inline WorkGang* ShenandoahHeap::workers() const {
|
||||
inline WorkerThreads* ShenandoahHeap::workers() const {
|
||||
return _workers;
|
||||
}
|
||||
|
||||
inline WorkGang* ShenandoahHeap::safepoint_workers() {
|
||||
inline WorkerThreads* ShenandoahHeap::safepoint_workers() {
|
||||
return _safepoint_workers;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,7 @@ ShenandoahClassUnloadingTask::ShenandoahClassUnloadingTask(ShenandoahPhaseTiming
|
||||
BoolObjectClosure* is_alive,
|
||||
uint num_workers,
|
||||
bool unloading_occurred) :
|
||||
AbstractGangTask("Shenandoah Class Unloading"),
|
||||
WorkerTask("Shenandoah Class Unloading"),
|
||||
_phase(phase),
|
||||
_unloading_occurred(unloading_occurred),
|
||||
_code_cache_task(num_workers, is_alive, unloading_occurred),
|
||||
|
@ -27,13 +27,13 @@
|
||||
|
||||
#include "gc/shared/parallelCleaning.hpp"
|
||||
#include "gc/shared/weakProcessor.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shenandoah/shenandoahPhaseTimings.hpp"
|
||||
#include "memory/iterator.hpp"
|
||||
|
||||
// Perform weak root cleaning at a pause
|
||||
template <typename IsAlive, typename KeepAlive>
|
||||
class ShenandoahParallelWeakRootsCleaningTask : public AbstractGangTask {
|
||||
class ShenandoahParallelWeakRootsCleaningTask : public WorkerTask {
|
||||
protected:
|
||||
ShenandoahPhaseTimings::Phase const _phase;
|
||||
WeakProcessor::Task _weak_processing_task;
|
||||
@ -51,7 +51,7 @@ public:
|
||||
};
|
||||
|
||||
// Perform class unloading at a pause
|
||||
class ShenandoahClassUnloadingTask : public AbstractGangTask {
|
||||
class ShenandoahClassUnloadingTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahPhaseTimings::Phase const _phase;
|
||||
bool _unloading_occurred;
|
||||
|
@ -38,7 +38,7 @@ ShenandoahParallelWeakRootsCleaningTask<IsAlive, KeepAlive>::ShenandoahParallelW
|
||||
IsAlive* is_alive,
|
||||
KeepAlive* keep_alive,
|
||||
uint num_workers) :
|
||||
AbstractGangTask("Shenandoah Weak Root Cleaning"),
|
||||
WorkerTask("Shenandoah Weak Root Cleaning"),
|
||||
_phase(phase),
|
||||
_weak_processing_task(num_workers),
|
||||
_is_alive(is_alive),
|
||||
|
@ -464,7 +464,7 @@ void ShenandoahReferenceProcessor::work() {
|
||||
}
|
||||
}
|
||||
|
||||
class ShenandoahReferenceProcessorTask : public AbstractGangTask {
|
||||
class ShenandoahReferenceProcessorTask : public WorkerTask {
|
||||
private:
|
||||
bool const _concurrent;
|
||||
ShenandoahPhaseTimings::Phase const _phase;
|
||||
@ -472,7 +472,7 @@ private:
|
||||
|
||||
public:
|
||||
ShenandoahReferenceProcessorTask(ShenandoahPhaseTimings::Phase phase, bool concurrent, ShenandoahReferenceProcessor* reference_processor) :
|
||||
AbstractGangTask("ShenandoahReferenceProcessorTask"),
|
||||
WorkerTask("ShenandoahReferenceProcessorTask"),
|
||||
_concurrent(concurrent),
|
||||
_phase(phase),
|
||||
_reference_processor(reference_processor) {
|
||||
@ -491,7 +491,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
void ShenandoahReferenceProcessor::process_references(ShenandoahPhaseTimings::Phase phase, WorkGang* workers, bool concurrent) {
|
||||
void ShenandoahReferenceProcessor::process_references(ShenandoahPhaseTimings::Phase phase, WorkerThreads* workers, bool concurrent) {
|
||||
|
||||
Atomic::release_store_fence(&_iterate_discovered_list_id, 0U);
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
class ShenandoahMarkRefsSuperClosure;
|
||||
class WorkGang;
|
||||
class WorkerThreads;
|
||||
|
||||
static const size_t reference_type_count = REF_PHANTOM + 1;
|
||||
typedef size_t Counters[reference_type_count];
|
||||
@ -179,7 +179,7 @@ public:
|
||||
|
||||
bool discover_reference(oop obj, ReferenceType type) override;
|
||||
|
||||
void process_references(ShenandoahPhaseTimings::Phase phase, WorkGang* workers, bool concurrent);
|
||||
void process_references(ShenandoahPhaseTimings::Phase phase, WorkerThreads* workers, bool concurrent);
|
||||
|
||||
const ReferenceProcessorStats& reference_process_stats() { return _stats; }
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include "gc/shared/strongRootsScope.hpp"
|
||||
#include "gc/shared/taskTerminator.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shenandoah/shenandoahClosures.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahMark.inline.hpp"
|
||||
#include "gc/shenandoah/shenandoahOopClosures.inline.hpp"
|
||||
@ -60,7 +60,7 @@ void ShenandoahInitMarkRootsClosure::do_oop_work(T* p) {
|
||||
ShenandoahMark::mark_through_ref<T>(p, _queue, _mark_context, false);
|
||||
}
|
||||
|
||||
class ShenandoahSTWMarkTask : public AbstractGangTask {
|
||||
class ShenandoahSTWMarkTask : public WorkerTask {
|
||||
private:
|
||||
ShenandoahSTWMark* const _mark;
|
||||
|
||||
@ -70,7 +70,7 @@ public:
|
||||
};
|
||||
|
||||
ShenandoahSTWMarkTask::ShenandoahSTWMarkTask(ShenandoahSTWMark* mark) :
|
||||
AbstractGangTask("Shenandoah STW mark"),
|
||||
WorkerTask("Shenandoah STW mark"),
|
||||
_mark(mark) {
|
||||
}
|
||||
|
||||
|
@ -421,7 +421,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahVerifierReachableTask : public AbstractGangTask {
|
||||
class ShenandoahVerifierReachableTask : public WorkerTask {
|
||||
private:
|
||||
const char* _label;
|
||||
ShenandoahVerifier::VerifyOptions _options;
|
||||
@ -435,7 +435,7 @@ public:
|
||||
ShenandoahLivenessData* ld,
|
||||
const char* label,
|
||||
ShenandoahVerifier::VerifyOptions options) :
|
||||
AbstractGangTask("Shenandoah Verifier Reachable Objects"),
|
||||
WorkerTask("Shenandoah Verifier Reachable Objects"),
|
||||
_label(label),
|
||||
_options(options),
|
||||
_heap(ShenandoahHeap::heap()),
|
||||
@ -484,7 +484,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ShenandoahVerifierMarkedRegionTask : public AbstractGangTask {
|
||||
class ShenandoahVerifierMarkedRegionTask : public WorkerTask {
|
||||
private:
|
||||
const char* _label;
|
||||
ShenandoahVerifier::VerifyOptions _options;
|
||||
@ -499,7 +499,7 @@ public:
|
||||
ShenandoahLivenessData* ld,
|
||||
const char* label,
|
||||
ShenandoahVerifier::VerifyOptions options) :
|
||||
AbstractGangTask("Shenandoah Verifier Marked Objects"),
|
||||
WorkerTask("Shenandoah Verifier Marked Objects"),
|
||||
_label(label),
|
||||
_options(options),
|
||||
_heap(ShenandoahHeap::heap()),
|
||||
|
@ -31,11 +31,11 @@
|
||||
|
||||
#include "logging/log.hpp"
|
||||
|
||||
ShenandoahWorkerScope::ShenandoahWorkerScope(WorkGang* workers, uint nworkers, const char* msg, bool check) :
|
||||
ShenandoahWorkerScope::ShenandoahWorkerScope(WorkerThreads* workers, uint nworkers, const char* msg, bool check) :
|
||||
_workers(workers) {
|
||||
assert(msg != NULL, "Missing message");
|
||||
|
||||
_n_workers = _workers->update_active_workers(nworkers);
|
||||
_n_workers = _workers->set_active_workers(nworkers);
|
||||
assert(_n_workers <= nworkers, "Must be");
|
||||
|
||||
log_info(gc, task)("Using %u of %u workers for %s",
|
||||
@ -51,10 +51,10 @@ ShenandoahWorkerScope::~ShenandoahWorkerScope() {
|
||||
"Active workers can not be changed within this scope");
|
||||
}
|
||||
|
||||
ShenandoahPushWorkerScope::ShenandoahPushWorkerScope(WorkGang* workers, uint nworkers, bool check) :
|
||||
ShenandoahPushWorkerScope::ShenandoahPushWorkerScope(WorkerThreads* workers, uint nworkers, bool check) :
|
||||
_old_workers(workers->active_workers()),
|
||||
_workers(workers) {
|
||||
_n_workers = _workers->update_active_workers(nworkers);
|
||||
_n_workers = _workers->set_active_workers(nworkers);
|
||||
assert(_n_workers <= nworkers, "Must be");
|
||||
|
||||
// bypass concurrent/parallel protocol check for non-regular paths, e.g. verifier, etc.
|
||||
@ -67,12 +67,12 @@ ShenandoahPushWorkerScope::~ShenandoahPushWorkerScope() {
|
||||
assert(_workers->active_workers() == _n_workers,
|
||||
"Active workers can not be changed within this scope");
|
||||
// Restore old worker value
|
||||
uint nworkers = _workers->update_active_workers(_old_workers);
|
||||
uint nworkers = _workers->set_active_workers(_old_workers);
|
||||
assert(nworkers == _old_workers, "Must be able to restore");
|
||||
}
|
||||
|
||||
GangWorker* ShenandoahWorkGang::install_worker(uint which) {
|
||||
GangWorker* worker = WorkGang::install_worker(which);
|
||||
WorkerThread* ShenandoahWorkerThreads::create_worker(uint id) {
|
||||
WorkerThread* worker = WorkerThreads::create_worker(id);
|
||||
ShenandoahThreadLocalData::create(worker);
|
||||
if (_initialize_gclab) {
|
||||
ShenandoahThreadLocalData::initialize_gclab(worker);
|
||||
|
@ -25,7 +25,7 @@
|
||||
#ifndef SHARE_GC_SHENANDOAH_SHENANDOAHWORKGROUP_HPP
|
||||
#define SHARE_GC_SHENANDOAH_SHENANDOAHWORKGROUP_HPP
|
||||
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shenandoah/shenandoahTaskqueue.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
@ -34,9 +34,9 @@ class ShenandoahObjToScanQueueSet;
|
||||
class ShenandoahWorkerScope : public StackObj {
|
||||
private:
|
||||
uint _n_workers;
|
||||
WorkGang* _workers;
|
||||
WorkerThreads* _workers;
|
||||
public:
|
||||
ShenandoahWorkerScope(WorkGang* workers, uint nworkers, const char* msg, bool do_check = true);
|
||||
ShenandoahWorkerScope(WorkerThreads* workers, uint nworkers, const char* msg, bool do_check = true);
|
||||
~ShenandoahWorkerScope();
|
||||
};
|
||||
|
||||
@ -44,25 +44,25 @@ class ShenandoahPushWorkerScope : StackObj {
|
||||
protected:
|
||||
uint _n_workers;
|
||||
uint _old_workers;
|
||||
WorkGang* _workers;
|
||||
WorkerThreads* _workers;
|
||||
|
||||
public:
|
||||
ShenandoahPushWorkerScope(WorkGang* workers, uint nworkers, bool do_check = true);
|
||||
ShenandoahPushWorkerScope(WorkerThreads* workers, uint nworkers, bool do_check = true);
|
||||
~ShenandoahPushWorkerScope();
|
||||
};
|
||||
|
||||
class ShenandoahWorkGang : public WorkGang {
|
||||
class ShenandoahWorkerThreads : public WorkerThreads {
|
||||
private:
|
||||
bool _initialize_gclab;
|
||||
public:
|
||||
ShenandoahWorkGang(const char* name,
|
||||
ShenandoahWorkerThreads(const char* name,
|
||||
uint workers) :
|
||||
WorkGang(name, workers), _initialize_gclab(false) {
|
||||
WorkerThreads(name, workers), _initialize_gclab(false) {
|
||||
}
|
||||
|
||||
// Create a GC worker and install it into the work gang.
|
||||
// Create a GC worker.
|
||||
// We need to initialize gclab for dynamic allocated workers
|
||||
GangWorker* install_worker(uint which);
|
||||
WorkerThread* create_worker(uint id);
|
||||
|
||||
void set_initialize_gclab() { assert(!_initialize_gclab, "Can only enable once"); _initialize_gclab = true; }
|
||||
};
|
||||
|
@ -266,7 +266,7 @@ void ZCollectedHeap::verify_nmethod(nmethod* nm) {
|
||||
// Does nothing
|
||||
}
|
||||
|
||||
WorkGang* ZCollectedHeap::safepoint_workers() {
|
||||
WorkerThreads* ZCollectedHeap::safepoint_workers() {
|
||||
return _runtime_workers.workers();
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ public:
|
||||
virtual void flush_nmethod(nmethod* nm);
|
||||
virtual void verify_nmethod(nmethod* nmethod);
|
||||
|
||||
virtual WorkGang* safepoint_workers();
|
||||
virtual WorkerThreads* safepoint_workers();
|
||||
|
||||
virtual void gc_threads_do(ThreadClosure* tc) const;
|
||||
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "gc/z/zThread.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
|
||||
class ZRuntimeWorkersInitializeTask : public AbstractGangTask {
|
||||
class ZRuntimeWorkersInitializeTask : public WorkerTask {
|
||||
private:
|
||||
const uint _nworkers;
|
||||
uint _started;
|
||||
@ -38,7 +38,7 @@ private:
|
||||
|
||||
public:
|
||||
ZRuntimeWorkersInitializeTask(uint nworkers) :
|
||||
AbstractGangTask("ZRuntimeWorkersInitializeTask"),
|
||||
WorkerTask("ZRuntimeWorkersInitializeTask"),
|
||||
_nworkers(nworkers),
|
||||
_started(0),
|
||||
_lock() {}
|
||||
@ -61,22 +61,22 @@ ZRuntimeWorkers::ZRuntimeWorkers() :
|
||||
_workers("RuntimeWorker",
|
||||
ParallelGCThreads) {
|
||||
|
||||
log_info_p(gc, init)("Runtime Workers: %u", _workers.total_workers());
|
||||
log_info_p(gc, init)("Runtime Workers: %u", _workers.max_workers());
|
||||
|
||||
// Initialize worker threads
|
||||
_workers.initialize_workers();
|
||||
_workers.update_active_workers(_workers.total_workers());
|
||||
if (_workers.active_workers() != _workers.total_workers()) {
|
||||
_workers.set_active_workers(_workers.max_workers());
|
||||
if (_workers.active_workers() != _workers.max_workers()) {
|
||||
vm_exit_during_initialization("Failed to create ZRuntimeWorkers");
|
||||
}
|
||||
|
||||
// Execute task to reduce latency in early safepoints,
|
||||
// which otherwise would have to take on any warmup costs.
|
||||
ZRuntimeWorkersInitializeTask task(_workers.total_workers());
|
||||
ZRuntimeWorkersInitializeTask task(_workers.max_workers());
|
||||
_workers.run_task(&task);
|
||||
}
|
||||
|
||||
WorkGang* ZRuntimeWorkers::workers() {
|
||||
WorkerThreads* ZRuntimeWorkers::workers() {
|
||||
return &_workers;
|
||||
}
|
||||
|
||||
|
@ -24,18 +24,18 @@
|
||||
#ifndef SHARE_GC_Z_ZRUNTIMEWORKERS_HPP
|
||||
#define SHARE_GC_Z_ZRUNTIMEWORKERS_HPP
|
||||
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
|
||||
class ThreadClosure;
|
||||
|
||||
class ZRuntimeWorkers {
|
||||
private:
|
||||
WorkGang _workers;
|
||||
WorkerThreads _workers;
|
||||
|
||||
public:
|
||||
ZRuntimeWorkers();
|
||||
|
||||
WorkGang* workers();
|
||||
WorkerThreads* workers();
|
||||
|
||||
void threads_do(ThreadClosure* tc) const;
|
||||
};
|
||||
|
@ -25,23 +25,23 @@
|
||||
#include "gc/z/zTask.hpp"
|
||||
#include "gc/z/zThread.hpp"
|
||||
|
||||
ZTask::GangTask::GangTask(ZTask* ztask, const char* name) :
|
||||
AbstractGangTask(name),
|
||||
_ztask(ztask) {}
|
||||
ZTask::Task::Task(ZTask* task, const char* name) :
|
||||
WorkerTask(name),
|
||||
_task(task) {}
|
||||
|
||||
void ZTask::GangTask::work(uint worker_id) {
|
||||
void ZTask::Task::work(uint worker_id) {
|
||||
ZThread::set_worker_id(worker_id);
|
||||
_ztask->work();
|
||||
_task->work();
|
||||
ZThread::clear_worker_id();
|
||||
}
|
||||
|
||||
ZTask::ZTask(const char* name) :
|
||||
_gang_task(this, name) {}
|
||||
_worker_task(this, name) {}
|
||||
|
||||
const char* ZTask::name() const {
|
||||
return _gang_task.name();
|
||||
return _worker_task.name();
|
||||
}
|
||||
|
||||
AbstractGangTask* ZTask::gang_task() {
|
||||
return &_gang_task;
|
||||
WorkerTask* ZTask::worker_task() {
|
||||
return &_worker_task;
|
||||
}
|
||||
|
@ -24,28 +24,28 @@
|
||||
#ifndef SHARE_GC_Z_ZTASK_HPP
|
||||
#define SHARE_GC_Z_ZTASK_HPP
|
||||
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
|
||||
class ZTask : public StackObj {
|
||||
private:
|
||||
class GangTask : public AbstractGangTask {
|
||||
class Task : public WorkerTask {
|
||||
private:
|
||||
ZTask* const _ztask;
|
||||
ZTask* const _task;
|
||||
|
||||
public:
|
||||
GangTask(ZTask* ztask, const char* name);
|
||||
Task(ZTask* task, const char* name);
|
||||
|
||||
virtual void work(uint worker_id);
|
||||
};
|
||||
|
||||
GangTask _gang_task;
|
||||
Task _worker_task;
|
||||
|
||||
public:
|
||||
ZTask(const char* name);
|
||||
|
||||
const char* name() const;
|
||||
AbstractGangTask* gang_task();
|
||||
WorkerTask* worker_task();
|
||||
|
||||
virtual void work() = 0;
|
||||
};
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "gc/z/zWorkers.hpp"
|
||||
#include "runtime/java.hpp"
|
||||
|
||||
class ZWorkersInitializeTask : public AbstractGangTask {
|
||||
class ZWorkersInitializeTask : public WorkerTask {
|
||||
private:
|
||||
const uint _nworkers;
|
||||
uint _started;
|
||||
@ -39,7 +39,7 @@ private:
|
||||
|
||||
public:
|
||||
ZWorkersInitializeTask(uint nworkers) :
|
||||
AbstractGangTask("ZWorkersInitializeTask"),
|
||||
WorkerTask("ZWorkersInitializeTask"),
|
||||
_nworkers(nworkers),
|
||||
_started(0),
|
||||
_lock() {}
|
||||
@ -66,20 +66,20 @@ ZWorkers::ZWorkers() :
|
||||
UseDynamicNumberOfGCThreads ? ConcGCThreads : MAX2(ConcGCThreads, ParallelGCThreads)) {
|
||||
|
||||
if (UseDynamicNumberOfGCThreads) {
|
||||
log_info_p(gc, init)("GC Workers: %u (dynamic)", _workers.total_workers());
|
||||
log_info_p(gc, init)("GC Workers: %u (dynamic)", _workers.max_workers());
|
||||
} else {
|
||||
log_info_p(gc, init)("GC Workers: %u/%u (static)", ConcGCThreads, _workers.total_workers());
|
||||
log_info_p(gc, init)("GC Workers: %u/%u (static)", ConcGCThreads, _workers.max_workers());
|
||||
}
|
||||
|
||||
// Initialize worker threads
|
||||
_workers.initialize_workers();
|
||||
_workers.update_active_workers(_workers.total_workers());
|
||||
if (_workers.active_workers() != _workers.total_workers()) {
|
||||
_workers.set_active_workers(_workers.max_workers());
|
||||
if (_workers.active_workers() != _workers.max_workers()) {
|
||||
vm_exit_during_initialization("Failed to create ZWorkers");
|
||||
}
|
||||
|
||||
// Execute task to register threads as workers
|
||||
ZWorkersInitializeTask task(_workers.total_workers());
|
||||
ZWorkersInitializeTask task(_workers.max_workers());
|
||||
_workers.run_task(&task);
|
||||
}
|
||||
|
||||
@ -89,13 +89,13 @@ uint ZWorkers::active_workers() const {
|
||||
|
||||
void ZWorkers::set_active_workers(uint nworkers) {
|
||||
log_info(gc, task)("Using %u workers", nworkers);
|
||||
_workers.update_active_workers(nworkers);
|
||||
_workers.set_active_workers(nworkers);
|
||||
}
|
||||
|
||||
void ZWorkers::run(ZTask* task) {
|
||||
log_debug(gc, task)("Executing Task: %s, Active Workers: %u", task->name(), active_workers());
|
||||
ZStatWorkers::at_start();
|
||||
_workers.run_task(task->gang_task());
|
||||
_workers.run_task(task->worker_task());
|
||||
ZStatWorkers::at_end();
|
||||
}
|
||||
|
||||
@ -104,12 +104,12 @@ void ZWorkers::run_all(ZTask* task) {
|
||||
const uint prev_active_workers = _workers.active_workers();
|
||||
|
||||
// Execute task using all workers
|
||||
_workers.update_active_workers(_workers.total_workers());
|
||||
_workers.set_active_workers(_workers.max_workers());
|
||||
log_debug(gc, task)("Executing Task: %s, Active Workers: %u", task->name(), active_workers());
|
||||
_workers.run_task(task->gang_task());
|
||||
_workers.run_task(task->worker_task());
|
||||
|
||||
// Restore number of active workers
|
||||
_workers.update_active_workers(prev_active_workers);
|
||||
_workers.set_active_workers(prev_active_workers);
|
||||
}
|
||||
|
||||
void ZWorkers::threads_do(ThreadClosure* tc) const {
|
||||
|
@ -24,14 +24,14 @@
|
||||
#ifndef SHARE_GC_Z_ZWORKERS_HPP
|
||||
#define SHARE_GC_Z_ZWORKERS_HPP
|
||||
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
|
||||
class ThreadClosure;
|
||||
class ZTask;
|
||||
|
||||
class ZWorkers {
|
||||
private:
|
||||
WorkGang _workers;
|
||||
WorkerThreads _workers;
|
||||
|
||||
public:
|
||||
ZWorkers();
|
||||
|
@ -94,8 +94,7 @@ DEBUG_ONLY(size_t Test_log_prefix_prefixer(char* buf, size_t len);)
|
||||
DEBUG_ONLY(LOG_PREFIX(Test_log_prefix_prefixer, LOG_TAGS(logging, test))) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, tlab)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, verify)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, verify, start)) \
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, workgang))
|
||||
LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, verify, start))
|
||||
|
||||
|
||||
// The empty prefix, used when there's no prefix defined.
|
||||
|
@ -196,8 +196,7 @@
|
||||
LOG_TAG(vmoperation) \
|
||||
LOG_TAG(vmthread) \
|
||||
LOG_TAG(vtables) \
|
||||
LOG_TAG(vtablestubs) \
|
||||
LOG_TAG(workgang)
|
||||
LOG_TAG(vtablestubs)
|
||||
|
||||
#define PREFIX_LOG_TAG(T) (LogTag::_##T)
|
||||
|
||||
|
@ -577,20 +577,21 @@ uintx HeapInspection::populate_table(KlassInfoTable* cit, BoolObjectClosure *fil
|
||||
if (parallel_thread_num > 1) {
|
||||
ResourceMark rm;
|
||||
|
||||
WorkGang* gang = Universe::heap()->safepoint_workers();
|
||||
if (gang != NULL) {
|
||||
// The GC provided a WorkGang to be used during a safepoint.
|
||||
WorkerThreads* workers = Universe::heap()->safepoint_workers();
|
||||
if (workers != NULL) {
|
||||
// The GC provided a WorkerThreads to be used during a safepoint.
|
||||
|
||||
// Can't run with more threads than provided by the WorkGang.
|
||||
WithUpdatedActiveWorkers update_and_restore(gang, parallel_thread_num);
|
||||
// Can't run with more threads than provided by the WorkerThreads.
|
||||
const uint capped_parallel_thread_num = MIN2(parallel_thread_num, workers->max_workers());
|
||||
WithActiveWorkers with_active_workers(workers, capped_parallel_thread_num);
|
||||
|
||||
ParallelObjectIterator* poi = Universe::heap()->parallel_object_iterator(gang->active_workers());
|
||||
ParallelObjectIterator* poi = Universe::heap()->parallel_object_iterator(workers->active_workers());
|
||||
if (poi != NULL) {
|
||||
// The GC supports parallel object iteration.
|
||||
|
||||
ParHeapInspectTask task(poi, cit, filter);
|
||||
// Run task with the active workers.
|
||||
gang->run_task(&task);
|
||||
workers->run_task(&task);
|
||||
|
||||
delete poi;
|
||||
if (task.success()) {
|
||||
|
@ -25,12 +25,12 @@
|
||||
#ifndef SHARE_MEMORY_HEAPINSPECTION_HPP
|
||||
#define SHARE_MEMORY_HEAPINSPECTION_HPP
|
||||
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/objArrayOop.hpp"
|
||||
#include "oops/oop.hpp"
|
||||
#include "oops/annotations.hpp"
|
||||
#include "utilities/macros.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
|
||||
class ParallelObjectIterator;
|
||||
|
||||
@ -226,7 +226,7 @@ class HeapInspection : public StackObj {
|
||||
// Parallel heap inspection task. Parallel inspection can fail due to
|
||||
// a native OOM when allocating memory for TL-KlassInfoTable.
|
||||
// _success will be set false on an OOM, and serial inspection tried.
|
||||
class ParHeapInspectTask : public AbstractGangTask {
|
||||
class ParHeapInspectTask : public WorkerTask {
|
||||
private:
|
||||
ParallelObjectIterator* _poi;
|
||||
KlassInfoTable* _shared_cit;
|
||||
@ -239,7 +239,7 @@ class ParHeapInspectTask : public AbstractGangTask {
|
||||
ParHeapInspectTask(ParallelObjectIterator* poi,
|
||||
KlassInfoTable* shared_cit,
|
||||
BoolObjectClosure* filter) :
|
||||
AbstractGangTask("Iterating heap"),
|
||||
WorkerTask("Iterating heap"),
|
||||
_poi(poi),
|
||||
_shared_cit(shared_cit),
|
||||
_filter(filter),
|
||||
|
@ -101,31 +101,6 @@ class NamedThread: public NonJavaThread {
|
||||
uint gc_id() { return _gc_id; }
|
||||
};
|
||||
|
||||
// Worker threads are named and have an id of an assigned work.
|
||||
class WorkerThread: public NamedThread {
|
||||
private:
|
||||
uint _id;
|
||||
public:
|
||||
static WorkerThread* current() {
|
||||
return WorkerThread::cast(Thread::current());
|
||||
}
|
||||
|
||||
static WorkerThread* cast(Thread* t) {
|
||||
assert(t->is_Worker_thread(), "incorrect cast to WorkerThread");
|
||||
return static_cast<WorkerThread*>(t);
|
||||
}
|
||||
|
||||
WorkerThread() : _id(0) { }
|
||||
virtual bool is_Worker_thread() const { return true; }
|
||||
|
||||
void set_id(uint work_id) { _id = work_id; }
|
||||
uint id() const { return _id; }
|
||||
|
||||
// Printing
|
||||
virtual const char* type_name() const { return "WorkerThread"; }
|
||||
|
||||
};
|
||||
|
||||
// A single WatcherThread is used for simulating timer interrupts.
|
||||
class WatcherThread: public NonJavaThread {
|
||||
friend class VMStructs;
|
||||
|
@ -37,7 +37,8 @@
|
||||
#include "gc/shared/gcLocker.hpp"
|
||||
#include "gc/shared/oopStorage.hpp"
|
||||
#include "gc/shared/strongRootsScope.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "gc/shared/workerUtils.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "logging/log.hpp"
|
||||
@ -515,7 +516,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class ParallelSPCleanupTask : public AbstractGangTask {
|
||||
class ParallelSPCleanupTask : public WorkerTask {
|
||||
private:
|
||||
SubTasksDone _subtasks;
|
||||
uint _num_workers;
|
||||
@ -539,7 +540,7 @@ private:
|
||||
|
||||
public:
|
||||
ParallelSPCleanupTask(uint num_workers) :
|
||||
AbstractGangTask("Parallel Safepoint Cleanup"),
|
||||
WorkerTask("Parallel Safepoint Cleanup"),
|
||||
_subtasks(SafepointSynchronize::SAFEPOINT_CLEANUP_NUM_TASKS),
|
||||
_num_workers(num_workers),
|
||||
_do_lazy_roots(!VMThread::vm_operation()->skip_thread_oop_barriers() &&
|
||||
@ -602,7 +603,7 @@ void SafepointSynchronize::do_cleanup_tasks() {
|
||||
|
||||
CollectedHeap* heap = Universe::heap();
|
||||
assert(heap != NULL, "heap not initialized yet?");
|
||||
WorkGang* cleanup_workers = heap->safepoint_workers();
|
||||
WorkerThreads* cleanup_workers = heap->safepoint_workers();
|
||||
if (cleanup_workers != NULL) {
|
||||
// Parallel cleanup using GC provided thread pool.
|
||||
uint num_cleanup_workers = cleanup_workers->active_workers();
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "code/nmethod.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "gc/shared/collectedHeap.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "logging/logStream.hpp"
|
||||
|
@ -99,7 +99,6 @@ class JavaThread;
|
||||
// - VMThread
|
||||
// - ConcurrentGCThread
|
||||
// - WorkerThread
|
||||
// - GangWorker
|
||||
// - WatcherThread
|
||||
// - JfrThreadSampler
|
||||
// - LogAsyncWriter
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "gc/shared/gcLocker.hpp"
|
||||
#include "gc/shared/gcVMOperations.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
@ -1853,7 +1853,7 @@ class DumperController : public CHeapObj<mtInternal> {
|
||||
};
|
||||
|
||||
// The VM operation that performs the heap dump
|
||||
class VM_HeapDumper : public VM_GC_Operation, public AbstractGangTask {
|
||||
class VM_HeapDumper : public VM_GC_Operation, public WorkerTask {
|
||||
private:
|
||||
static VM_HeapDumper* _global_dumper;
|
||||
static DumpWriter* _global_writer;
|
||||
@ -1973,7 +1973,7 @@ class VM_HeapDumper : public VM_GC_Operation, public AbstractGangTask {
|
||||
GCCause::_heap_dump /* GC Cause */,
|
||||
0 /* total full collections, dummy, ignored */,
|
||||
gc_before_heap_dump),
|
||||
AbstractGangTask("dump heap") {
|
||||
WorkerTask("dump heap") {
|
||||
_local_writer = writer;
|
||||
_gc_before_heap_dump = gc_before_heap_dump;
|
||||
_klass_map = new (ResourceObj::C_HEAP, mtServiceability) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, mtServiceability);
|
||||
@ -2248,16 +2248,16 @@ void VM_HeapDumper::doit() {
|
||||
set_global_dumper();
|
||||
set_global_writer();
|
||||
|
||||
WorkGang* gang = ch->safepoint_workers();
|
||||
WorkerThreads* workers = ch->safepoint_workers();
|
||||
|
||||
if (gang == NULL) {
|
||||
if (workers == NULL) {
|
||||
// Use serial dump, set dumper threads and writer threads number to 1.
|
||||
_num_dumper_threads=1;
|
||||
_num_writer_threads=1;
|
||||
work(0);
|
||||
} else {
|
||||
prepare_parallel_dump(gang->active_workers());
|
||||
gang->run_task(this);
|
||||
prepare_parallel_dump(workers->active_workers());
|
||||
workers->run_task(this);
|
||||
finish_parallel_dump();
|
||||
}
|
||||
|
||||
|
@ -24,30 +24,30 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "gc/g1/g1BatchedGangTask.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/g1/g1BatchedTask.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "unittest.hpp"
|
||||
|
||||
class G1BatchedGangTaskWorkers : AllStatic {
|
||||
static WorkGang* _work_gang;
|
||||
static WorkGang* work_gang() {
|
||||
if (_work_gang == nullptr) {
|
||||
_work_gang = new WorkGang("G1 Small Workers", MaxWorkers);
|
||||
_work_gang->initialize_workers();
|
||||
_work_gang->update_active_workers(MaxWorkers);
|
||||
class G1BatchedTaskWorkers : AllStatic {
|
||||
static WorkerThreads* _workers;
|
||||
static WorkerThreads* workers() {
|
||||
if (_workers == nullptr) {
|
||||
_workers = new WorkerThreads("G1 Small Workers", MaxWorkers);
|
||||
_workers->initialize_workers();
|
||||
_workers->set_active_workers(MaxWorkers);
|
||||
}
|
||||
return _work_gang;
|
||||
return _workers;
|
||||
}
|
||||
|
||||
public:
|
||||
static const uint MaxWorkers = 4;
|
||||
static void run_task(AbstractGangTask* task) {
|
||||
work_gang()->run_task(task);
|
||||
static void run_task(WorkerTask* task) {
|
||||
workers()->run_task(task);
|
||||
}
|
||||
};
|
||||
|
||||
WorkGang* G1BatchedGangTaskWorkers::_work_gang = nullptr;
|
||||
WorkerThreads* G1BatchedTaskWorkers::_workers = nullptr;
|
||||
|
||||
class G1TestSubTask : public G1AbstractSubTask {
|
||||
mutable uint _phase;
|
||||
@ -96,7 +96,7 @@ public:
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
// Called by G1BatchedGangTask to provide information about the the maximum
|
||||
// Called by G1BatchedTask to provide information about the the maximum
|
||||
// number of workers for all subtasks after it has been determined.
|
||||
void set_max_workers(uint max_workers) override {
|
||||
assert(max_workers >= 1, "must be");
|
||||
@ -140,18 +140,18 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class G1TestBatchedGangTask : public G1BatchedGangTask {
|
||||
class G1TestBatchedTask : public G1BatchedTask {
|
||||
public:
|
||||
G1TestBatchedGangTask() : G1BatchedGangTask("Batched Gang Test Task", nullptr) {
|
||||
G1TestBatchedTask() : G1BatchedTask("Batched Test Task", nullptr) {
|
||||
add_serial_task(new G1SerialTestSubTask());
|
||||
add_parallel_task(new G1ParallelTestSubTask());
|
||||
}
|
||||
};
|
||||
|
||||
TEST_VM(G1BatchedGangTask, check) {
|
||||
G1TestBatchedGangTask task;
|
||||
TEST_VM(G1BatchedTask, check) {
|
||||
G1TestBatchedTask task;
|
||||
uint tasks = task.num_workers_estimate();
|
||||
ASSERT_EQ(tasks, 3u);
|
||||
task.set_max_workers(G1BatchedGangTaskWorkers::MaxWorkers);
|
||||
G1BatchedGangTaskWorkers::run_task(&task);
|
||||
task.set_max_workers(G1BatchedTaskWorkers::MaxWorkers);
|
||||
G1BatchedTaskWorkers::run_task(&task);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "gc/g1/g1CardSetMemory.hpp"
|
||||
#include "gc/g1/heapRegionRemSet.hpp"
|
||||
#include "gc/shared/gcTraceTime.inline.hpp"
|
||||
#include "gc/shared/workgroup.hpp"
|
||||
#include "gc/shared/workerThread.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "unittest.hpp"
|
||||
#include "utilities/powerOfTwo.hpp"
|
||||
@ -44,15 +44,15 @@ class G1CardSetTest : public ::testing::Test {
|
||||
}
|
||||
};
|
||||
|
||||
static WorkGang* _workers;
|
||||
static WorkerThreads* _workers;
|
||||
static uint _max_workers;
|
||||
|
||||
static WorkGang* workers() {
|
||||
static WorkerThreads* workers() {
|
||||
if (_workers == NULL) {
|
||||
_max_workers = os::processor_count();
|
||||
_workers = new WorkGang("G1CardSetTest Work Gang", _max_workers);
|
||||
_workers = new WorkerThreads("G1CardSetTest Workers", _max_workers);
|
||||
_workers->initialize_workers();
|
||||
_workers->update_active_workers(_max_workers);
|
||||
_workers->set_active_workers(_max_workers);
|
||||
}
|
||||
return _workers;
|
||||
}
|
||||
@ -85,7 +85,7 @@ public:
|
||||
static void iterate_cards(G1CardSet* card_set, G1CardSet::G1CardSetCardIterator* cl);
|
||||
};
|
||||
|
||||
WorkGang* G1CardSetTest::_workers = NULL;
|
||||
WorkerThreads* G1CardSetTest::_workers = NULL;
|
||||
uint G1CardSetTest::_max_workers = 0;
|
||||
|
||||
void G1CardSetTest::add_cards(G1CardSet* card_set, uint cards_per_region, uint* cards, uint num_cards, G1AddCardResult* results) {
|
||||
@ -376,7 +376,7 @@ void G1CardSetTest::cardset_basic_test() {
|
||||
}
|
||||
}
|
||||
|
||||
class G1CardSetMtTestTask : public AbstractGangTask {
|
||||
class G1CardSetMtTestTask : public WorkerTask {
|
||||
G1CardSet* _card_set;
|
||||
|
||||
size_t _added;
|
||||
@ -384,7 +384,7 @@ class G1CardSetMtTestTask : public AbstractGangTask {
|
||||
|
||||
public:
|
||||
G1CardSetMtTestTask(G1CardSet* card_set) :
|
||||
AbstractGangTask(""),
|
||||
WorkerTask(""),
|
||||
_card_set(card_set),
|
||||
_added(0),
|
||||
_found(0) { }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user