src/share/vm/utilities/workgroup.hpp

changeset 3294
bca17e38de00
parent 3156
f08d439fab8c
child 3357
441e946dc1af
     1.1 --- a/src/share/vm/utilities/workgroup.hpp	Tue Nov 22 04:47:10 2011 -0500
     1.2 +++ b/src/share/vm/utilities/workgroup.hpp	Tue Aug 09 10:16:01 2011 -0700
     1.3 @@ -96,11 +96,14 @@
     1.4  
     1.5  protected:
     1.6    // Constructor and desctructor: only construct subclasses.
     1.7 -  AbstractGangTask(const char* name) {
     1.8 +  AbstractGangTask(const char* name)
     1.9 +  {
    1.10      NOT_PRODUCT(_name = name);
    1.11      _counter = 0;
    1.12    }
    1.13    virtual ~AbstractGangTask() { }
    1.14 +
    1.15 +public:
    1.16  };
    1.17  
    1.18  class AbstractGangTaskWOopQueues : public AbstractGangTask {
    1.19 @@ -116,6 +119,7 @@
    1.20    OopTaskQueueSet* queues() { return _queues; }
    1.21  };
    1.22  
    1.23 +
    1.24  // Class AbstractWorkGang:
    1.25  // An abstract class representing a gang of workers.
    1.26  // You subclass this to supply an implementation of run_task().
    1.27 @@ -130,6 +134,8 @@
    1.28    virtual void run_task(AbstractGangTask* task) = 0;
    1.29    // Stop and terminate all workers.
    1.30    virtual void stop();
    1.31 +  // Return true if more workers should be applied to the task.
    1.32 +  virtual bool needs_more_workers() const { return true; }
    1.33  public:
    1.34    // Debugging.
    1.35    const char* name() const;
    1.36 @@ -287,20 +293,62 @@
    1.37    AbstractWorkGang* gang() const { return _gang; }
    1.38  };
    1.39  
    1.40 +// Dynamic number of worker threads
    1.41 +//
    1.42 +// This type of work gang is used to run different numbers of
    1.43 +// worker threads at different times.  The
    1.44 +// number of workers run for a task is "_active_workers"
    1.45 +// instead of "_total_workers" in a WorkGang.  The method
    1.46 +// "needs_more_workers()" returns true until "_active_workers"
    1.47 +// have been started and returns false afterwards.  The
    1.48 +// implementation of "needs_more_workers()" in WorkGang always
    1.49 +// returns true so that all workers are started.  The method
    1.50 +// "loop()" in GangWorker was modified to ask "needs_more_workers()"
    1.51 +// in its loop to decide if it should start working on a task.
    1.52 +// A worker in "loop()" waits for notification on the WorkGang
    1.53 +// monitor and execution of each worker as it checks for work
    1.54 +// is serialized via the same monitor.  The "needs_more_workers()"
    1.55 +// call is serialized and additionally the calculation for the
    1.56 +// "part" (effectively the worker id for executing the task) is
    1.57 +// serialized to give each worker a unique "part".  Workers that
    1.58 +// are not needed for this tasks (i.e., "_active_workers" have
    1.59 +// been started before it, continue to wait for work.
    1.60 +
    1.61  class FlexibleWorkGang: public WorkGang {
    1.62 +  // The currently active workers in this gang.
    1.63 +  // This is a number that is dynamically adjusted
    1.64 +  // and checked in the run_task() method at each invocation.
    1.65 +  // As described above _active_workers determines the number
    1.66 +  // of threads started on a task.  It must also be used to
    1.67 +  // determine completion.
    1.68 +
    1.69   protected:
    1.70    int _active_workers;
    1.71   public:
    1.72    // Constructor and destructor.
    1.73 +  // Initialize active_workers to a minimum value.  Setting it to
    1.74 +  // the parameter "workers" will initialize it to a maximum
    1.75 +  // value which is not desirable.
    1.76    FlexibleWorkGang(const char* name, int workers,
    1.77                     bool are_GC_task_threads,
    1.78                     bool  are_ConcurrentGC_threads) :
    1.79 -    WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads) {
    1.80 -    _active_workers = ParallelGCThreads;
    1.81 -  };
    1.82 +    WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads),
    1.83 +    _active_workers(UseDynamicNumberOfGCThreads ? 1 : ParallelGCThreads) {};
    1.84    // Accessors for fields
    1.85    virtual int active_workers() const { return _active_workers; }
    1.86 -  void set_active_workers(int v) { _active_workers = v; }
    1.87 +  void set_active_workers(int v) {
    1.88 +    assert(v <= _total_workers,
    1.89 +           "Trying to set more workers active than there are");
    1.90 +    _active_workers = MIN2(v, _total_workers);
    1.91 +    assert(v != 0, "Trying to set active workers to 0");
    1.92 +    _active_workers = MAX2(1, _active_workers);
    1.93 +    assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers,
    1.94 +           "Unless dynamic should use total workers");
    1.95 +  }
    1.96 +  virtual void run_task(AbstractGangTask* task);
    1.97 +  virtual bool needs_more_workers() const {
    1.98 +    return _started_workers < _active_workers;
    1.99 +  }
   1.100  };
   1.101  
   1.102  // Work gangs in garbage collectors: 2009-06-10
   1.103 @@ -357,6 +405,11 @@
   1.104  class SubTasksDone: public CHeapObj {
   1.105    jint* _tasks;
   1.106    int _n_tasks;
   1.107 +  // _n_threads is used to determine when a sub task is done.
   1.108 +  // It does not control how many threads will execute the subtask
   1.109 +  // but must be initialized to the number that do execute the task
   1.110 +  // in order to correctly decide when the subtask is done (all the
   1.111 +  // threads working on the task have finished).
   1.112    int _n_threads;
   1.113    jint _threads_completed;
   1.114  #ifdef ASSERT

mercurial