8264788: Make SequentialSubTasksDone use-once

Reviewed-by: ayang, sjohanss
This commit is contained in:
Thomas Schatzl 2021-04-15 08:11:01 +00:00
parent 0793fcbbca
commit 125a8479a9
5 changed files with 23 additions and 91 deletions

View File

@ -2056,18 +2056,15 @@ public:
MarkFromRootsTask(uint active_workers) :
AbstractGangTask("MarkFromRootsTask"),
_strong_roots_scope(active_workers),
_subtasks(),
_subtasks(ParallelRootType::sentinel),
_terminator(active_workers, ParCompactionManager::oop_task_queues()),
_active_workers(active_workers) {
_subtasks.set_n_threads(active_workers);
_subtasks.set_n_tasks(ParallelRootType::sentinel);
}
virtual void work(uint worker_id) {
for (uint task = 0; _subtasks.try_claim_task(task); /*empty*/ ) {
mark_from_roots_work(static_cast<ParallelRootType::Value>(task), worker_id);
}
_subtasks.all_tasks_completed();
PCAddThreadRootsMarkingTaskClosure closure(worker_id);
Threads::possibly_parallel_threads_do(true /*parallel */, &closure);

View File

@ -304,14 +304,12 @@ public:
bool is_empty) :
AbstractGangTask("ScavengeRootsTask"),
_strong_roots_scope(active_workers),
_subtasks(),
_subtasks(ParallelRootType::sentinel),
_old_gen(old_gen),
_gen_top(gen_top),
_active_workers(active_workers),
_is_empty(is_empty),
_terminator(active_workers, PSPromotionManager::vm_thread_promotion_manager()->stack_array_depth()) {
_subtasks.set_n_threads(active_workers);
_subtasks.set_n_tasks(ParallelRootType::sentinel);
}
virtual void work(uint worker_id) {
@ -346,7 +344,6 @@ public:
for (uint root_type = 0; _subtasks.try_claim_task(root_type); /* empty */ ) {
scavenge_roots_work(static_cast<ParallelRootType::Value>(root_type), worker_id);
}
_subtasks.all_tasks_completed();
PSThreadRootsTaskClosure closure(worker_id);
Threads::possibly_parallel_threads_do(true /*parallel */, &closure);

View File

@ -104,18 +104,15 @@ public:
while (_sub_tasks.try_claim_task(/* reference */ task_id)) {
_preserved_marks_set->get(task_id)->restore_and_increment(_total_size_addr);
}
_sub_tasks.all_tasks_completed();
}
ParRestoreTask(uint worker_num,
PreservedMarksSet* preserved_marks_set,
ParRestoreTask(PreservedMarksSet* preserved_marks_set,
volatile size_t* total_size_addr)
: AbstractGangTask("Parallel Preserved Mark Restoration"),
_preserved_marks_set(preserved_marks_set),
_sub_tasks(preserved_marks_set->num()),
_total_size_addr(total_size_addr) {
_sub_tasks.set_n_threads(worker_num);
_sub_tasks.set_n_tasks(preserved_marks_set->num());
}
}
};
void PreservedMarksSet::restore(WorkGang* workers) {
@ -127,7 +124,7 @@ void PreservedMarksSet::restore(WorkGang* workers) {
for (uint i = 0; i < _num; i += 1) {
total_size_before += get(i)->size();
}
#endif // def ASSERT
#endif // ASSERT
if (workers == NULL) {
for (uint i = 0; i < num(); i += 1) {
@ -135,7 +132,7 @@ void PreservedMarksSet::restore(WorkGang* workers) {
get(i)->restore();
}
} else {
ParRestoreTask task(workers->active_workers(), this, &total_size);
ParRestoreTask task(this, &total_size);
workers->run_task(&task);
}

View File

@ -399,39 +399,10 @@ SubTasksDone::~SubTasksDone() {
// *** SequentialSubTasksDone
void SequentialSubTasksDone::clear() {
_n_tasks = _n_claimed = 0;
_n_threads = _n_completed = 0;
}
bool SequentialSubTasksDone::valid() {
return _n_threads > 0;
}
bool SequentialSubTasksDone::try_claim_task(uint& t) {
t = _n_claimed;
while (t < _n_tasks) {
uint res = Atomic::cmpxchg(&_n_claimed, t, t+1);
if (res == t) {
return true;
}
t = res;
t = _num_claimed;
if (t < _num_tasks) {
t = Atomic::add(&_num_claimed, 1u) - 1;
}
return false;
}
bool SequentialSubTasksDone::all_tasks_completed() {
uint complete = _n_completed;
while (true) {
uint res = Atomic::cmpxchg(&_n_completed, complete, complete+1);
if (res == complete) {
break;
}
complete = res;
}
if (complete+1 == _n_threads) {
clear();
return true;
}
return false;
return t < _num_tasks;
}

View File

@ -346,57 +346,27 @@ public:
// 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). Note that unlike the above class this is
// a stack object - is there any reason for it not to be?
// set scanning).
class SequentialSubTasksDone : public StackObj {
protected:
uint _n_tasks; // Total number of tasks available.
volatile uint _n_claimed; // Number of tasks claimed.
// _n_threads is used to determine when a sub task is done.
// See comments on SubTasksDone::_n_threads
uint _n_threads; // Total number of parallel threads.
volatile uint _n_completed; // Number of completed threads.
class SequentialSubTasksDone : public CHeapObj<mtInternal> {
void clear();
uint _num_tasks; // Total number of tasks available.
volatile uint _num_claimed; // Number of tasks claimed.
NONCOPYABLE(SequentialSubTasksDone);
public:
SequentialSubTasksDone() {
clear();
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);
}
~SequentialSubTasksDone() {}
// True iff the object is in a valid state.
bool valid();
// number of tasks
uint n_tasks() const { return _n_tasks; }
// Get/set the number of parallel threads doing the tasks to t.
// Should be called before the task starts but it is safe
// to call this once a task is running provided that all
// threads agree on the number of threads.
uint n_threads() { return _n_threads; }
void set_n_threads(uint t) { _n_threads = t; }
// Set the number of tasks to be claimed to t. As above,
// should be called before the tasks start but it is safe
// to call this once a task is running provided all threads
// agree on the number of tasks.
void set_n_tasks(uint t) { _n_tasks = t; }
// 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.
// 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);
// The calling thread asserts that it has attempted to claim
// all the tasks it possibly can in the sequence. Every thread
// claiming tasks must promise call this. Returns true if this
// is the last thread to complete so that the thread can perform
// cleanup if necessary.
bool all_tasks_completed();
};
#endif // SHARE_GC_SHARED_WORKGROUP_HPP