Skip to content
Permalink
Browse files
8234446: Post-CMS workgroup hierarchy cleanup
Reviewed-by: tschatzl, rkennke
  • Loading branch information
albertnetymk committed May 3, 2021
1 parent ac760c7 commit 80941f475f7f3bd479f1ab75287f0ffe7935ad05
@@ -50,25 +50,22 @@ class WorkerManager : public AllStatic {
// 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.
template <class WorkerType>
static uint add_workers (WorkerType* holder,
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.
template <class WorkerType>
static void log_worker_creation(WorkerType* holder,
static void log_worker_creation(WorkGang* workers,
uint previous_created_workers,
uint active_workers,
uint created_workers,
bool initializing);
};

template <class WorkerType>
uint WorkerManager::add_workers(WorkerType* holder,
uint WorkerManager::add_workers(WorkGang* workers,
uint active_workers,
uint total_workers,
uint created_workers,
@@ -79,15 +76,13 @@ uint WorkerManager::add_workers(WorkerType* holder,
for (uint worker_id = start; worker_id < end; worker_id += 1) {
WorkerThread* new_worker = NULL;
if (initializing || !InjectGCWorkerCreationFailure) {
new_worker = holder->install_worker(worker_id);
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");
if (new_worker != NULL) {
delete new_worker;
}
delete new_worker;
if (initializing) {
vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create worker GC thread. Out of system resources.");
}
@@ -103,16 +98,15 @@ uint WorkerManager::add_workers(WorkerType* holder,
return created_workers;
}

template <class WorkerType>
void WorkerManager::log_worker_creation(WorkerType* holder,
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, holder->group_name(), previous_created_workers, active_workers, created_workers);
initializing_msg, workers->group_name(), previous_created_workers, active_workers, created_workers);
}
}

@@ -34,77 +34,6 @@
#include "runtime/semaphore.hpp"
#include "runtime/thread.inline.hpp"

// Definitions of WorkGang methods.

AbstractWorkGang::AbstractWorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads) :
_workers(NULL),
_total_workers(workers),
_active_workers(UseDynamicNumberOfGCThreads ? 1U : workers),
_created_workers(0),
_name(name),
_are_GC_task_threads(are_GC_task_threads),
_are_ConcurrentGC_threads(are_ConcurrentGC_threads)
{ }


// The current implementation will exit if the allocation
// of any worker fails.
void AbstractWorkGang::initialize_workers() {
log_develop_trace(gc, workgang)("Constructing work gang %s with %u threads", name(), total_workers());
_workers = NEW_C_HEAP_ARRAY(AbstractGangWorker*, total_workers(), mtInternal);
add_workers(true);
}


AbstractGangWorker* AbstractWorkGang::install_worker(uint worker_id) {
AbstractGangWorker* new_worker = allocate_worker(worker_id);
set_thread(worker_id, new_worker);
return new_worker;
}

void AbstractWorkGang::add_workers(bool initializing) {
add_workers(_active_workers, initializing);
}

void AbstractWorkGang::add_workers(uint active_workers, bool initializing) {

os::ThreadType worker_type;
if (are_ConcurrentGC_threads()) {
worker_type = os::cgc_thread;
} else {
worker_type = os::pgc_thread;
}
uint previous_created_workers = _created_workers;

_created_workers = WorkerManager::add_workers(this,
active_workers,
_total_workers,
_created_workers,
worker_type,
initializing);
_active_workers = MIN2(_created_workers, _active_workers);

WorkerManager::log_worker_creation(this, previous_created_workers, _active_workers, _created_workers, initializing);
}

AbstractGangWorker* AbstractWorkGang::worker(uint i) const {
// Array index bounds checking.
AbstractGangWorker* 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 AbstractWorkGang::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));
}
}

static void run_foreground_task_if_needed(AbstractGangTask* task, uint num_workers,
bool add_foreground_work) {
if (add_foreground_work) {
@@ -198,20 +127,77 @@ class GangTaskDispatcher : public CHeapObj<mtGC> {
}
}
};
// Definitions of WorkGang methods.

WorkGang::WorkGang(const char* name,
uint workers,
bool are_GC_task_threads,
bool are_ConcurrentGC_threads) :
AbstractWorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads),
WorkGang::WorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads) :
_workers(NULL),
_total_workers(workers),
_active_workers(UseDynamicNumberOfGCThreads ? 1U : workers),
_created_workers(0),
_name(name),
_are_GC_task_threads(are_GC_task_threads),
_are_ConcurrentGC_threads(are_ConcurrentGC_threads),
_dispatcher(new GangTaskDispatcher())
{ }
{ }

WorkGang::~WorkGang() {
delete _dispatcher;
}

AbstractGangWorker* WorkGang::allocate_worker(uint worker_id) {
// 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) {
os::ThreadType worker_type;
if (are_ConcurrentGC_threads()) {
worker_type = os::cgc_thread;
} else {
worker_type = os::pgc_thread;
}
uint previous_created_workers = _created_workers;

_created_workers = WorkerManager::add_workers(this,
_active_workers,
_total_workers,
_created_workers,
worker_type,
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);
}

@@ -230,41 +216,25 @@ void WorkGang::run_task(AbstractGangTask* task, uint num_workers, bool add_foreg
update_active_workers(old_num_workers);
}

AbstractGangWorker::AbstractGangWorker(AbstractWorkGang* gang, uint id) {
GangWorker::GangWorker(WorkGang* gang, uint id) {
_gang = gang;
set_id(id);
set_name("%s#%d", gang->name(), id);
}

void AbstractGangWorker::run() {
void GangWorker::run() {
initialize();
loop();
}

void AbstractGangWorker::initialize() {
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");
}

bool AbstractGangWorker::is_GC_task_thread() const {
return gang()->are_GC_task_threads();
}

bool AbstractGangWorker::is_ConcurrentGC_thread() const {
return gang()->are_ConcurrentGC_threads();
}

void AbstractGangWorker::print_on(outputStream* st) const {
st->print("\"%s\" ", name());
Thread::print_on(st);
st->cr();
}

void AbstractGangWorker::print() const { print_on(tty); }

WorkData GangWorker::wait_for_task() {
return gang()->dispatcher()->worker_wait_for_task();
}

0 comments on commit 80941f4

Please sign in to comment.