< prev index next >
src/share/vm/gc/shared/workgroup.hpp
Print this page
*** 23,33 ****
*/
#ifndef SHARE_VM_GC_SHARED_WORKGROUP_HPP
#define SHARE_VM_GC_SHARED_WORKGROUP_HPP
! #include "runtime/thread.inline.hpp"
// Task class hierarchy:
// AbstractGangTask
//
// Gang/Group class hierarchy:
--- 23,37 ----
*/
#ifndef SHARE_VM_GC_SHARED_WORKGROUP_HPP
#define SHARE_VM_GC_SHARED_WORKGROUP_HPP
! #include "memory/allocation.hpp"
! #include "runtime/globals.hpp"
! #include "runtime/thread.hpp"
! #include "utilities/debug.hpp"
! #include "utilities/globalDefinitions.hpp"
// Task class hierarchy:
// AbstractGangTask
//
// Gang/Group class hierarchy:
*** 41,52 ****
// YieldingFlexibleGangWorker (defined in another file)
// Forward declarations of classes defined here
class AbstractGangWorker;
! class GangWorker;
! class WorkData;
// An abstract task to be worked on by a gang.
// You subclass this to supply your own work() method
class AbstractGangTask VALUE_OBJ_CLASS_SPEC {
const char* _name;
--- 45,56 ----
// YieldingFlexibleGangWorker (defined in another file)
// Forward declarations of classes defined here
class AbstractGangWorker;
! class Semaphore;
! class WorkGang;
// An abstract task to be worked on by a gang.
// You subclass this to supply your own work() method
class AbstractGangTask VALUE_OBJ_CLASS_SPEC {
const char* _name;
*** 60,69 ****
--- 64,100 ----
// Debugging accessor for the name.
const char* name() const { return _name; }
};
+ struct WorkData {
+ AbstractGangTask* _task;
+ uint _worker_id;
+ WorkData(AbstractGangTask* task, uint worker_id) : _task(task), _worker_id(worker_id) {}
+ };
+
+ // Interface to handle the synchronization between the coordinator thread and the worker threads,
+ // when a task is dispatched out to the worker threads.
+ class GangTaskDispatcher : public CHeapObj<mtGC> {
+ public:
+ virtual ~GangTaskDispatcher() {}
+
+ // Coordinator API.
+
+ // Distributes the task out to num_workers workers.
+ // Returns when the task has been completed by all workers.
+ virtual void coordinator_execute_on_workers(AbstractGangTask* task, uint num_workers) = 0;
+
+ // Worker API.
+
+ // Waits for a task to become available to the worker.
+ // Returns when the worker has been assigned a task.
+ virtual WorkData worker_wait_for_task() = 0;
+
+ // Signal to the coordinator that the worker is done with the assigned task.
+ virtual void worker_done_with_task() = 0;
+ };
// 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 of workers.
class AbstractWorkGang : public CHeapObj<mtInternal> {
*** 89,100 ****
_active_workers(UseDynamicNumberOfGCThreads ? 1U : workers),
_are_GC_task_threads(are_GC_task_threads),
_are_ConcurrentGC_threads(are_ConcurrentGC_threads)
{ }
- virtual AbstractGangWorker* allocate_worker(uint which) = 0;
-
// Initialize workers in the gang. Return true if initialization succeeded.
bool initialize_workers();
bool are_GC_task_threads() const { return _are_GC_task_threads; }
bool are_ConcurrentGC_threads() const { return _are_ConcurrentGC_threads; }
--- 120,129 ----
*** 129,231 ****
// Printing
void print_worker_threads_on(outputStream *st) const;
void print_worker_threads() const {
print_worker_threads_on(tty);
}
};
// An class representing a gang of workers.
class WorkGang: public AbstractWorkGang {
! private:
// Never deleted.
~WorkGang();
public:
WorkGang(const char* name,
uint workers,
bool are_GC_task_threads,
bool are_ConcurrentGC_threads);
// Run a task, returns when the task is done.
virtual void run_task(AbstractGangTask* task);
- void run_task(AbstractGangTask* task, uint no_of_parallel_workers);
-
- // Return true if more workers should be applied to the task.
- virtual bool needs_more_workers() const {
- return _started_workers < _active_workers;
- }
protected:
- // The monitor which protects these data,
- // and notifies of changes in it.
- Monitor* _monitor;
- // The task for this gang.
- AbstractGangTask* _task;
- // A sequence number for the current task.
- int _sequence_number;
- // The number of started workers.
- uint _started_workers;
- // The number of finished workers.
- uint _finished_workers;
-
- public:
virtual AbstractGangWorker* allocate_worker(uint which);
- // Accessors for fields
- Monitor* monitor() const {
- return _monitor;
- }
- AbstractGangTask* task() const {
- return _task;
- }
- int sequence_number() const {
- return _sequence_number;
- }
- uint started_workers() const {
- return _started_workers;
- }
- uint finished_workers() const {
- return _finished_workers;
- }
- // Predicates.
- bool is_idle() const {
- return (task() == NULL);
- }
- // Return the Ith gang worker.
- GangWorker* gang_worker(uint i) const;
-
- protected:
- friend class GangWorker;
- // Note activation and deactivation of workers.
- // These methods should only be called with the mutex held.
- void internal_worker_poll(WorkData* data) const;
- void internal_note_start();
- void internal_note_finish();
- };
-
- class WorkData: public StackObj {
- // This would be a struct, but I want accessor methods.
private:
! AbstractGangTask* _task;
! int _sequence_number;
! public:
! // Constructor and destructor
! WorkData() {
! _task = NULL;
! _sequence_number = 0;
! }
! ~WorkData() {
! }
! AbstractGangTask* task() const { return _task; }
! void set_task(AbstractGangTask* value) { _task = value; }
! int sequence_number() const { return _sequence_number; }
! void set_sequence_number(int value) { _sequence_number = value; }
};
// Several instances of this class run in parallel as workers for a gang.
class AbstractGangWorker: public WorkerThread {
public:
- // Constructors and destructor.
AbstractGangWorker(AbstractWorkGang* gang, uint id);
// The only real method: run a task for the gang.
virtual void run();
// Predicate for Thread
--- 158,205 ----
// Printing
void print_worker_threads_on(outputStream *st) const;
void print_worker_threads() const {
print_worker_threads_on(tty);
}
+
+ protected:
+ virtual AbstractGangWorker* allocate_worker(uint which) = 0;
};
// An class representing a gang of workers.
class WorkGang: public AbstractWorkGang {
! // To get access to the GangTaskDispatcher instance.
! friend class GangWorker;
!
// Never deleted.
~WorkGang();
+
+ GangTaskDispatcher* const _dispatcher;
+ GangTaskDispatcher* dispatcher()const {
+ return _dispatcher;
+ }
+
public:
WorkGang(const char* name,
uint workers,
bool are_GC_task_threads,
bool are_ConcurrentGC_threads);
// Run a task, returns when the task is done.
virtual void run_task(AbstractGangTask* task);
protected:
virtual AbstractGangWorker* allocate_worker(uint which);
private:
! void print_worker_started_task(AbstractGangTask* task, uint worker_id);
! void print_worker_finished_task(AbstractGangTask* task, uint worker_id);
};
// Several instances of this class run in parallel as workers for a gang.
class AbstractGangWorker: public WorkerThread {
public:
AbstractGangWorker(AbstractWorkGang* gang, uint id);
// The only real method: run a task for the gang.
virtual void run();
// Predicate for Thread
*** 250,283 ****
protected:
virtual void loop();
private:
WorkGang* gang() const { return (WorkGang*)_gang; }
};
- // Dynamic number of worker threads
- //
- // This type of work gang is used to run different numbers of
- // worker threads at different times. The
- // number of workers run for a task is "_active_workers"
- // instead of "_total_workers" in a WorkGang. The method
- // "needs_more_workers()" returns true until "_active_workers"
- // have been started and returns false afterwards. The
- // implementation of "needs_more_workers()" in WorkGang always
- // returns true so that all workers are started. The method
- // "loop()" in GangWorker was modified to ask "needs_more_workers()"
- // in its loop to decide if it should start working on a task.
- // A worker in "loop()" waits for notification on the WorkGang
- // monitor and execution of each worker as it checks for work
- // is serialized via the same monitor. The "needs_more_workers()"
- // call is serialized and additionally the calculation for the
- // "part" (effectively the worker id for executing the task) is
- // serialized to give each worker a unique "part". Workers that
- // are not needed for this tasks (i.e., "_active_workers" have
- // been started before it, continue to wait for work.
-
// 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 {
--- 224,243 ----
protected:
virtual void loop();
private:
+ WorkData wait_for_task();
+ void run_task(WorkData work);
+ void signal_task_done();
+
+ void print_task_started(WorkData data);
+ void print_task_done(WorkData data);
+
WorkGang* gang() const { return (WorkGang*)_gang; }
};
// 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 {
< prev index next >