void WorkGang::run_task(AbstractGangTask* task) { // This thread is executed by the VM thread which does not block // on ordinary MutexLocker's. MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); if (TraceWorkGang) { tty->print_cr("Running work gang %s task %s", name(), task->name()); } // Tell all the workers to run a task. assert(task != NULL, "Running a null task"); // Initialize. _task = task; _sequence_number += 1; _started_workers = 0; _finished_workers = 0; // Tell the workers to get to work. monitor()->notify_all(); // Wait for them to be finished while (finished_workers() < total_workers()) { if (TraceWorkGang) { tty->print_cr("Waiting in work gang %s: %d/%d finished sequence %d", name(), finished_workers(), total_workers(), _sequence_number); } monitor()->wait(/* no_safepoint_check */ true); } _task = NULL; if (TraceWorkGang) { tty->print_cr("/nFinished work gang %s: %d/%d sequence %d", name(), finished_workers(), total_workers(), _sequence_number); } }
// The current implementation will exit if the allocation // of any worker fails. Still, return a boolean so that // a future implementation can possibly do a partial // initialization of the workers and report such to the // caller. bool WorkGang::initialize_workers() { if (TraceWorkGang) { tty->print_cr("Constructing work gang %s with %d threads", name(), total_workers()); } _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, total_workers(), mtInternal); if (gang_workers() == NULL) { vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GangWorker array."); return false; } os::ThreadType worker_type; if (are_ConcurrentGC_threads()) { worker_type = os::cgc_thread; } else { worker_type = os::pgc_thread; } for (uint worker = 0; worker < total_workers(); worker += 1) { GangWorker* new_worker = allocate_worker(worker); assert(new_worker != NULL, "Failed to allocate GangWorker"); _gang_workers[worker] = new_worker; if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) { vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create worker GC thread. Out of system resources."); return false; } if (!DisableStartThread) { os::start_thread(new_worker); } } return true; }
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); }
void YieldingFlexibleWorkGang::start_task(YieldingFlexibleGangTask* new_task) { MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); assert(task() == NULL, "Gang currently tied to a task"); assert(new_task != NULL, "Null task"); // Bind task to gang _task = new_task; new_task->set_gang(this); // Establish 2-way binding to support yielding _sequence_number++; uint requested_size = new_task->requested_size(); assert(requested_size >= 0, "Should be non-negative"); if (requested_size != 0) { _active_workers = MIN2(requested_size, total_workers()); } else { _active_workers = active_workers(); } new_task->set_actual_size(_active_workers); new_task->set_for_termination(_active_workers); assert(_started_workers == 0, "Tabula rasa non"); assert(_finished_workers == 0, "Tabula rasa non"); assert(_yielded_workers == 0, "Tabula rasa non"); yielding_task()->set_status(ACTIVE); // Wake up all the workers, the first few will get to work, // and the rest will go back to sleep monitor()->notify_all(); wait_for_gang(); }
void AbstractWorkGang::threads_do(ThreadClosure* tc) const { assert(tc != NULL, "Null ThreadClosure"); uint num_thr = total_workers(); for (uint i = 0; i < num_thr; i++) { tc->do_thread(gang_worker(i)); } }
void AbstractWorkGang::print_worker_threads_on(outputStream* st) const { uint num_thr = total_workers(); for (uint i = 0; i < num_thr; i++) { gang_worker(i)->print_on(st); st->cr(); } }
void WorkGang::print_worker_threads() const { uint num_thr = total_workers(); for (uint i = 0; i < num_thr; i++) { gang_worker(i)->print(); tty->cr(); } }
void WorkGang::stop_task() { // Tell all workers to terminate, then wait for them to become inactive. MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag); if (TraceWorkGang) { tty->print_cr("Stopping work gang %s task %s", name(), task()->name()); } _task = NULL; _terminate = true; monitor()->notify_all(); while (finished_workers() < total_workers()) { if (TraceWorkGang) { tty->print_cr("Waiting in work gang %s: %d/%d finished", name(), finished_workers(), total_workers()); } monitor()->wait(/* no_safepoint_check */ true); } }
GangWorker* AbstractWorkGang::gang_worker(uint i) const { // Array index bounds checking. GangWorker* result = NULL; assert(gang_workers() != NULL, "No workers for indexing"); assert(((i >= 0) && (i < total_workers())), "Worker index out of bounds"); result = _gang_workers[i]; assert(result != NULL, "Indexing to null worker"); return result; }
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; }
AbstractWorkGang::~AbstractWorkGang() { if (TraceWorkGang) { tty->print_cr("Destructing work gang %s", name()); } stop(); // stop all the workers for (uint worker = 0; worker < total_workers(); worker += 1) { delete gang_worker(worker); } delete gang_workers(); delete monitor(); }
WorkGang::~WorkGang() { if (TraceWorkGang) { tty->print_cr("Destructing work gang %s", name()); } stop_task(); for (int worker = 0; worker < total_workers(); worker += 1) { delete gang_worker(worker); } delete gang_workers(); delete monitor(); }
/** * 创建并初始化所有的工作线程 */ bool WorkGang::initialize_workers() { if (TraceWorkGang) { tty->print_cr("Constructing work gang %s with %d threads", name(), total_workers()); } _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, total_workers()); if (gang_workers() == NULL) { vm_exit_out_of_memory(0, "Cannot create GangWorker array."); return false; } os::ThreadType worker_type; if (are_ConcurrentGC_threads()) { worker_type = os::cgc_thread; } else { worker_type = os::pgc_thread; } printf("%s[%d] [tid: %lu]: 开始创建 %u 个 %s Gc线程.\n", __FILE__, __LINE__, pthread_self(), total_workers(), worker_type == os::cgc_thread? "Concurrent" : "Parallel"); for (uint worker = 0; worker < total_workers(); worker += 1) { GangWorker* new_worker = allocate_worker(worker); assert(new_worker != NULL, "Failed to allocate GangWorker"); _gang_workers[worker] = new_worker; if (new_worker == NULL || !os::create_thread(new_worker, worker_type)) { vm_exit_out_of_memory(0, "Cannot create worker GC thread. Out of system resources."); return false; } if (!DisableStartThread) { os::start_thread(new_worker); } } return true; }
WorkGang::WorkGang(const char* name, int workers, bool are_GC_threads) { // Save arguments. _name = name; _total_workers = workers; _are_GC_threads = are_GC_threads; if (TraceWorkGang) { tty->print_cr("Constructing work gang %s with %d threads", name, workers); } // Other initialization. if (are_GC_threads) { _monitor = new Monitor(/* priority */ Mutex::safepoint, /* name */ "WorkGroup monitor", /* allow_vm_block */ true); } else { _monitor = new Monitor(/* priority */ Mutex::leaf, /* name */ "WorkGroup monitor", /* allow_vm_block */ false); } assert(monitor() != NULL, "Failed to allocate monitor"); _terminate = false; _task = NULL; _sequence_number = 0; _started_workers = 0; _finished_workers = 0; _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, workers); assert(gang_workers() != NULL, "Failed to allocate gang workers"); for (int worker = 0; worker < total_workers(); worker += 1) { GangWorker* new_worker = new GangWorker(this, worker); assert(new_worker != NULL, "Failed to allocate GangWorker"); _gang_workers[worker] = new_worker; bool os_thread_create = os::create_thread(new_worker, os::gc_thread); assert(os_thread_create, "os thread create failed"); if (!DisableStartThread) { os::start_thread(new_worker); } } }
void WorkGang::run_task(AbstractGangTask* task) { run_task(task, total_workers()); }
// 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); if (_workers == NULL) { vm_exit_out_of_memory(0, OOM_MALLOC_ERROR, "Cannot create GangWorker array."); } add_workers(true); }