Ejemplo n.º 1
0
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);
    }
}
Ejemplo n.º 2
0
// 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;
}
Ejemplo n.º 3
0
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();
}
Ejemplo n.º 5
0
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));
  }
}
Ejemplo n.º 6
0
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();
  }
}
Ejemplo n.º 7
0
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();
  }
}
Ejemplo n.º 8
0
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);
  }
}
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
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;
}
Ejemplo n.º 11
0
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();
}
Ejemplo n.º 12
0
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();
}
Ejemplo n.º 13
0
/**
 * 创建并初始化所有的工作线程
 */
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;
}
Ejemplo n.º 14
0
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);
    }
  }
}
Ejemplo n.º 15
0
void WorkGang::run_task(AbstractGangTask* task) {
  run_task(task, total_workers());
}
Ejemplo n.º 16
0
// 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);
}