94 // ??? Or can the run method adjust priority as needed? |
94 // ??? Or can the run method adjust priority as needed? |
95 int _counter; |
95 int _counter; |
96 |
96 |
97 protected: |
97 protected: |
98 // Constructor and desctructor: only construct subclasses. |
98 // Constructor and desctructor: only construct subclasses. |
99 AbstractGangTask(const char* name) { |
99 AbstractGangTask(const char* name) |
|
100 { |
100 NOT_PRODUCT(_name = name); |
101 NOT_PRODUCT(_name = name); |
101 _counter = 0; |
102 _counter = 0; |
102 } |
103 } |
103 virtual ~AbstractGangTask() { } |
104 virtual ~AbstractGangTask() { } |
|
105 |
|
106 public: |
104 }; |
107 }; |
105 |
108 |
106 class AbstractGangTaskWOopQueues : public AbstractGangTask { |
109 class AbstractGangTaskWOopQueues : public AbstractGangTask { |
107 OopTaskQueueSet* _queues; |
110 OopTaskQueueSet* _queues; |
108 ParallelTaskTerminator _terminator; |
111 ParallelTaskTerminator _terminator; |
285 |
291 |
286 public: |
292 public: |
287 AbstractWorkGang* gang() const { return _gang; } |
293 AbstractWorkGang* gang() const { return _gang; } |
288 }; |
294 }; |
289 |
295 |
|
296 // Dynamic number of worker threads |
|
297 // |
|
298 // This type of work gang is used to run different numbers of |
|
299 // worker threads at different times. The |
|
300 // number of workers run for a task is "_active_workers" |
|
301 // instead of "_total_workers" in a WorkGang. The method |
|
302 // "needs_more_workers()" returns true until "_active_workers" |
|
303 // have been started and returns false afterwards. The |
|
304 // implementation of "needs_more_workers()" in WorkGang always |
|
305 // returns true so that all workers are started. The method |
|
306 // "loop()" in GangWorker was modified to ask "needs_more_workers()" |
|
307 // in its loop to decide if it should start working on a task. |
|
308 // A worker in "loop()" waits for notification on the WorkGang |
|
309 // monitor and execution of each worker as it checks for work |
|
310 // is serialized via the same monitor. The "needs_more_workers()" |
|
311 // call is serialized and additionally the calculation for the |
|
312 // "part" (effectively the worker id for executing the task) is |
|
313 // serialized to give each worker a unique "part". Workers that |
|
314 // are not needed for this tasks (i.e., "_active_workers" have |
|
315 // been started before it, continue to wait for work. |
|
316 |
290 class FlexibleWorkGang: public WorkGang { |
317 class FlexibleWorkGang: public WorkGang { |
|
318 // The currently active workers in this gang. |
|
319 // This is a number that is dynamically adjusted |
|
320 // and checked in the run_task() method at each invocation. |
|
321 // As described above _active_workers determines the number |
|
322 // of threads started on a task. It must also be used to |
|
323 // determine completion. |
|
324 |
291 protected: |
325 protected: |
292 int _active_workers; |
326 int _active_workers; |
293 public: |
327 public: |
294 // Constructor and destructor. |
328 // Constructor and destructor. |
|
329 // Initialize active_workers to a minimum value. Setting it to |
|
330 // the parameter "workers" will initialize it to a maximum |
|
331 // value which is not desirable. |
295 FlexibleWorkGang(const char* name, int workers, |
332 FlexibleWorkGang(const char* name, int workers, |
296 bool are_GC_task_threads, |
333 bool are_GC_task_threads, |
297 bool are_ConcurrentGC_threads) : |
334 bool are_ConcurrentGC_threads) : |
298 WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads) { |
335 WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads), |
299 _active_workers = ParallelGCThreads; |
336 _active_workers(UseDynamicNumberOfGCThreads ? 1 : ParallelGCThreads) {}; |
300 }; |
|
301 // Accessors for fields |
337 // Accessors for fields |
302 virtual int active_workers() const { return _active_workers; } |
338 virtual int active_workers() const { return _active_workers; } |
303 void set_active_workers(int v) { _active_workers = v; } |
339 void set_active_workers(int v) { |
|
340 assert(v <= _total_workers, |
|
341 "Trying to set more workers active than there are"); |
|
342 _active_workers = MIN2(v, _total_workers); |
|
343 assert(v != 0, "Trying to set active workers to 0"); |
|
344 _active_workers = MAX2(1, _active_workers); |
|
345 assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers, |
|
346 "Unless dynamic should use total workers"); |
|
347 } |
|
348 virtual void run_task(AbstractGangTask* task); |
|
349 virtual bool needs_more_workers() const { |
|
350 return _started_workers < _active_workers; |
|
351 } |
304 }; |
352 }; |
305 |
353 |
306 // Work gangs in garbage collectors: 2009-06-10 |
354 // Work gangs in garbage collectors: 2009-06-10 |
307 // |
355 // |
308 // SharedHeap - work gang for stop-the-world parallel collection. |
356 // SharedHeap - work gang for stop-the-world parallel collection. |