< prev index next >
src/share/vm/gc/shared/workgroup.hpp
Print this page
*** 23,160 ****
*/
#ifndef SHARE_VM_GC_SHARED_WORKGROUP_HPP
#define SHARE_VM_GC_SHARED_WORKGROUP_HPP
- #include "gc/shared/taskqueue.hpp"
#include "runtime/thread.inline.hpp"
// Task class hierarchy:
// AbstractGangTask
- // AbstractGangTaskWOopQueues
//
// Gang/Group class hierarchy:
// AbstractWorkGang
// WorkGang
- // FlexibleWorkGang
// YieldingFlexibleWorkGang (defined in another file)
//
// Worker class hierarchy:
! // GangWorker (subclass of WorkerThread)
// YieldingFlexibleGangWorker (defined in another file)
// Forward declarations of classes defined here
! class WorkGang;
class GangWorker;
- class YieldingFlexibleGangWorker;
- class YieldingFlexibleGangTask;
class WorkData;
- class AbstractWorkGang;
// 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 {
! public:
// The abstract work method.
// The argument tells you which member of the gang you are.
virtual void work(uint worker_id) = 0;
// Debugging accessor for the name.
! const char* name() const PRODUCT_RETURN_(return NULL;);
! int counter() { return _counter; }
! void set_counter(int value) { _counter = value; }
! int *address_of_counter() { return &_counter; }
!
! // RTTI
! NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const {
! return false;
! })
- private:
- NOT_PRODUCT(const char* _name;)
- // ??? Should a task have a priority associated with it?
- // ??? Or can the run method adjust priority as needed?
- int _counter;
! protected:
! // Constructor and desctructor: only construct subclasses.
! AbstractGangTask(const char* name)
! {
! NOT_PRODUCT(_name = name);
! _counter = 0;
! }
! ~AbstractGangTask() { }
! public:
! };
- class AbstractGangTaskWOopQueues : public AbstractGangTask {
- OopTaskQueueSet* _queues;
- ParallelTaskTerminator _terminator;
public:
! AbstractGangTaskWOopQueues(const char* name, OopTaskQueueSet* queues, uint n_threads) :
! AbstractGangTask(name), _queues(queues), _terminator(n_threads, _queues) {}
! ParallelTaskTerminator* terminator() { return &_terminator; }
! OopTaskQueueSet* queues() { return _queues; }
! };
! // Class AbstractWorkGang:
! // An abstract class representing a gang of workers.
! // You subclass this to supply an implementation of run_task().
! class AbstractWorkGang: public CHeapObj<mtInternal> {
! protected:
! // Work gangs are never deleted, so no need to cleanup.
! ~AbstractWorkGang() { ShouldNotReachHere(); }
public:
! // Constructor.
! AbstractWorkGang(const char* name, bool are_GC_task_threads,
bool are_ConcurrentGC_threads);
! // Run a task, returns when the task is done (or terminated).
! virtual void run_task(AbstractGangTask* task) = 0;
// Return true if more workers should be applied to the task.
! virtual bool needs_more_workers() const { return true; }
! public:
! // Debugging.
! const char* name() const;
protected:
- // Initialize only instance data.
- const bool _are_GC_task_threads;
- const bool _are_ConcurrentGC_threads;
- // Printing support.
- const char* _name;
// The monitor which protects these data,
// and notifies of changes in it.
Monitor* _monitor;
- // The count of the number of workers in the gang.
- uint _total_workers;
- // The array of worker threads for this gang.
- // This is only needed for cleaning up.
- GangWorker** _gang_workers;
// 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:
// Accessors for fields
Monitor* monitor() const {
return _monitor;
}
- uint total_workers() const {
- return _total_workers;
- }
- virtual uint active_workers() const {
- return _total_workers;
- }
- GangWorker** gang_workers() const {
- return _gang_workers;
- }
AbstractGangTask* task() const {
return _task;
}
int sequence_number() const {
return _sequence_number;
--- 23,180 ----
*/
#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:
// AbstractWorkGang
// WorkGang
// YieldingFlexibleWorkGang (defined in another file)
//
// Worker class hierarchy:
! // AbstractGangWorker (subclass of WorkerThread)
! // GangWorker
// 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;
!
! public:
! AbstractGangTask(const char* name) : _name(name) {}
!
// The abstract work method.
// The argument tells you which member of the gang you are.
virtual void work(uint worker_id) = 0;
// Debugging accessor for the name.
! const char* name() const { return _name; }
! };
! // 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> {
! protected:
! // The array of worker threads for this gang.
! AbstractGangWorker** _workers;
! // The count of the number of workers in the gang.
! uint _total_workers;
! // The currently active workers in this gang.
! uint _active_workers;
! // Printing support.
! const char* _name;
! private:
! // Initialize only instance data.
! const bool _are_GC_task_threads;
! const bool _are_ConcurrentGC_threads;
public:
! AbstractWorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads) :
! _name(name),
! _total_workers(workers),
! _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; }
!
! uint total_workers() const { return _total_workers; }
!
! virtual uint active_workers() const {
! assert(_active_workers <= _total_workers,
! err_msg("_active_workers: %u > _total_workers: %u", _active_workers, _total_workers));
! assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
! "Unless dynamic should use total workers");
! return _active_workers;
! }
! void set_active_workers(uint v) {
! assert(v <= _total_workers,
! "Trying to set more workers active than there are");
! _active_workers = MIN2(v, _total_workers);
! assert(v != 0, "Trying to set active workers to 0");
! _active_workers = MAX2(1U, _active_workers);
! assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
! "Unless dynamic should use total workers");
! }
!
! // Return the Ith worker.
! AbstractGangWorker* worker(uint i) const;
!
! void threads_do(ThreadClosure* tc) const;
!
! // Debugging.
! const char* name() const { return _name; }
!
! // 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;
*** 163,196 ****
return _started_workers;
}
uint finished_workers() const {
return _finished_workers;
}
- bool are_GC_task_threads() const {
- return _are_GC_task_threads;
- }
- bool are_ConcurrentGC_threads() const {
- return _are_ConcurrentGC_threads;
- }
// Predicates.
bool is_idle() const {
return (task() == NULL);
}
// Return the Ith gang worker.
GangWorker* gang_worker(uint i) const;
- void threads_do(ThreadClosure* tc) const;
-
- // Printing
- void print_worker_threads_on(outputStream *st) const;
- void print_worker_threads() const {
- print_worker_threads_on(tty);
- }
-
protected:
friend class GangWorker;
- friend class YieldingFlexibleGangWorker;
// 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();
--- 183,201 ----
*** 211,268 ****
}
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; }
-
- YieldingFlexibleGangTask* yf_task() const {
- return (YieldingFlexibleGangTask*)_task;
- }
- };
-
- // Class WorkGang:
- class WorkGang: public AbstractWorkGang {
- public:
- // Constructor
- WorkGang(const char* name, uint workers,
- bool are_GC_task_threads, bool are_ConcurrentGC_threads);
- // Run a task, returns when the task is done (or terminated).
- virtual void run_task(AbstractGangTask* task);
- void run_task(AbstractGangTask* task, uint no_of_parallel_workers);
- // Allocate a worker and return a pointer to it.
- virtual GangWorker* allocate_worker(uint which);
- // Initialize workers in the gang. Return true if initialization
- // succeeded. The type of the worker can be overridden in a derived
- // class with the appropriate implementation of allocate_worker().
- bool initialize_workers();
};
- // Class GangWorker:
// Several instances of this class run in parallel as workers for a gang.
! class GangWorker: public WorkerThread {
public:
// Constructors and destructor.
! GangWorker(AbstractWorkGang* gang, uint id);
// The only real method: run a task for the gang.
virtual void run();
// Predicate for Thread
virtual bool is_GC_task_thread() const;
virtual bool is_ConcurrentGC_thread() const;
// Printing
void print_on(outputStream* st) const;
virtual void print() const { print_on(tty); }
protected:
AbstractWorkGang* _gang;
virtual void initialize();
! virtual void loop();
- public:
AbstractWorkGang* gang() const { return _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"
--- 216,262 ----
}
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
virtual bool is_GC_task_thread() const;
virtual bool is_ConcurrentGC_thread() const;
// Printing
void print_on(outputStream* st) const;
virtual void print() const { print_on(tty); }
+
protected:
AbstractWorkGang* _gang;
virtual void initialize();
! virtual void loop() = 0;
AbstractWorkGang* gang() const { return _gang; }
};
+ class GangWorker: public AbstractGangWorker {
+ public:
+ GangWorker(WorkGang* gang, uint id) : AbstractGangWorker(gang, id) {}
+
+ 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"
*** 280,330 ****
// "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.
- class FlexibleWorkGang: public WorkGang {
- // The currently active workers in this gang.
- // This is a number that is dynamically adjusted
- // and checked in the run_task() method at each invocation.
- // As described above _active_workers determines the number
- // of threads started on a task. It must also be used to
- // determine completion.
-
- protected:
- uint _active_workers;
- public:
- // Constructor and destructor.
- FlexibleWorkGang(const char* name, uint workers,
- bool are_GC_task_threads,
- bool are_ConcurrentGC_threads) :
- WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads),
- _active_workers(UseDynamicNumberOfGCThreads ? 1U : workers) {}
-
- // Accessors for fields.
- virtual uint active_workers() const {
- assert(_active_workers <= _total_workers,
- err_msg("_active_workers: %u > _total_workers: %u", _active_workers, _total_workers));
- assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
- "Unless dynamic should use total workers");
- return _active_workers;
- }
- void set_active_workers(uint v) {
- assert(v <= _total_workers,
- "Trying to set more workers active than there are");
- _active_workers = MIN2(v, _total_workers);
- assert(v != 0, "Trying to set active workers to 0");
- _active_workers = MAX2(1U, _active_workers);
- assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
- "Unless dynamic should use total workers");
- }
- virtual void run_task(AbstractGangTask* task);
- virtual bool needs_more_workers() const {
- return _started_workers < _active_workers;
- }
- };
-
// 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 {
--- 274,283 ----
< prev index next >