66 // You subclass this to supply your own work() method |
66 // You subclass this to supply your own work() method |
67 class AbstractGangTask VALUE_OBJ_CLASS_SPEC { |
67 class AbstractGangTask VALUE_OBJ_CLASS_SPEC { |
68 public: |
68 public: |
69 // The abstract work method. |
69 // The abstract work method. |
70 // The argument tells you which member of the gang you are. |
70 // The argument tells you which member of the gang you are. |
71 virtual void work(int i) = 0; |
71 virtual void work(uint worker_id) = 0; |
72 |
72 |
73 // This method configures the task for proper termination. |
73 // This method configures the task for proper termination. |
74 // Some tasks do not have any requirements on termination |
74 // Some tasks do not have any requirements on termination |
75 // and may inherit this method that does nothing. Some |
75 // and may inherit this method that does nothing. Some |
76 // tasks do some coordination on termination and override |
76 // tasks do some coordination on termination and override |
147 const char* _name; |
147 const char* _name; |
148 // The monitor which protects these data, |
148 // The monitor which protects these data, |
149 // and notifies of changes in it. |
149 // and notifies of changes in it. |
150 Monitor* _monitor; |
150 Monitor* _monitor; |
151 // The count of the number of workers in the gang. |
151 // The count of the number of workers in the gang. |
152 int _total_workers; |
152 uint _total_workers; |
153 // Whether the workers should terminate. |
153 // Whether the workers should terminate. |
154 bool _terminate; |
154 bool _terminate; |
155 // The array of worker threads for this gang. |
155 // The array of worker threads for this gang. |
156 // This is only needed for cleaning up. |
156 // This is only needed for cleaning up. |
157 GangWorker** _gang_workers; |
157 GangWorker** _gang_workers; |
158 // The task for this gang. |
158 // The task for this gang. |
159 AbstractGangTask* _task; |
159 AbstractGangTask* _task; |
160 // A sequence number for the current task. |
160 // A sequence number for the current task. |
161 int _sequence_number; |
161 int _sequence_number; |
162 // The number of started workers. |
162 // The number of started workers. |
163 int _started_workers; |
163 uint _started_workers; |
164 // The number of finished workers. |
164 // The number of finished workers. |
165 int _finished_workers; |
165 uint _finished_workers; |
166 public: |
166 public: |
167 // Accessors for fields |
167 // Accessors for fields |
168 Monitor* monitor() const { |
168 Monitor* monitor() const { |
169 return _monitor; |
169 return _monitor; |
170 } |
170 } |
171 int total_workers() const { |
171 uint total_workers() const { |
172 return _total_workers; |
172 return _total_workers; |
173 } |
173 } |
174 virtual int active_workers() const { |
174 virtual uint active_workers() const { |
175 return _total_workers; |
175 return _total_workers; |
176 } |
176 } |
177 bool terminate() const { |
177 bool terminate() const { |
178 return _terminate; |
178 return _terminate; |
179 } |
179 } |
184 return _task; |
184 return _task; |
185 } |
185 } |
186 int sequence_number() const { |
186 int sequence_number() const { |
187 return _sequence_number; |
187 return _sequence_number; |
188 } |
188 } |
189 int started_workers() const { |
189 uint started_workers() const { |
190 return _started_workers; |
190 return _started_workers; |
191 } |
191 } |
192 int finished_workers() const { |
192 uint finished_workers() const { |
193 return _finished_workers; |
193 return _finished_workers; |
194 } |
194 } |
195 bool are_GC_task_threads() const { |
195 bool are_GC_task_threads() const { |
196 return _are_GC_task_threads; |
196 return _are_GC_task_threads; |
197 } |
197 } |
253 |
253 |
254 // Class WorkGang: |
254 // Class WorkGang: |
255 class WorkGang: public AbstractWorkGang { |
255 class WorkGang: public AbstractWorkGang { |
256 public: |
256 public: |
257 // Constructor |
257 // Constructor |
258 WorkGang(const char* name, int workers, |
258 WorkGang(const char* name, uint workers, |
259 bool are_GC_task_threads, bool are_ConcurrentGC_threads); |
259 bool are_GC_task_threads, bool are_ConcurrentGC_threads); |
260 // Run a task, returns when the task is done (or terminated). |
260 // Run a task, returns when the task is done (or terminated). |
261 virtual void run_task(AbstractGangTask* task); |
261 virtual void run_task(AbstractGangTask* task); |
262 void run_task(AbstractGangTask* task, uint no_of_parallel_workers); |
262 void run_task(AbstractGangTask* task, uint no_of_parallel_workers); |
263 // Allocate a worker and return a pointer to it. |
263 // Allocate a worker and return a pointer to it. |
264 virtual GangWorker* allocate_worker(int which); |
264 virtual GangWorker* allocate_worker(uint which); |
265 // Initialize workers in the gang. Return true if initialization |
265 // Initialize workers in the gang. Return true if initialization |
266 // succeeded. The type of the worker can be overridden in a derived |
266 // succeeded. The type of the worker can be overridden in a derived |
267 // class with the appropriate implementation of allocate_worker(). |
267 // class with the appropriate implementation of allocate_worker(). |
268 bool initialize_workers(); |
268 bool initialize_workers(); |
269 }; |
269 }; |
321 // As described above _active_workers determines the number |
321 // As described above _active_workers determines the number |
322 // of threads started on a task. It must also be used to |
322 // of threads started on a task. It must also be used to |
323 // determine completion. |
323 // determine completion. |
324 |
324 |
325 protected: |
325 protected: |
326 int _active_workers; |
326 uint _active_workers; |
327 public: |
327 public: |
328 // Constructor and destructor. |
328 // Constructor and destructor. |
329 // Initialize active_workers to a minimum value. Setting it to |
329 // Initialize active_workers to a minimum value. Setting it to |
330 // the parameter "workers" will initialize it to a maximum |
330 // the parameter "workers" will initialize it to a maximum |
331 // value which is not desirable. |
331 // value which is not desirable. |
332 FlexibleWorkGang(const char* name, int workers, |
332 FlexibleWorkGang(const char* name, uint workers, |
333 bool are_GC_task_threads, |
333 bool are_GC_task_threads, |
334 bool are_ConcurrentGC_threads) : |
334 bool are_ConcurrentGC_threads) : |
335 WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads), |
335 WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads), |
336 _active_workers(UseDynamicNumberOfGCThreads ? 1 : ParallelGCThreads) {}; |
336 _active_workers(UseDynamicNumberOfGCThreads ? 1U : ParallelGCThreads) {} |
337 // Accessors for fields |
337 // Accessors for fields |
338 virtual int active_workers() const { return _active_workers; } |
338 virtual uint active_workers() const { return _active_workers; } |
339 void set_active_workers(int v) { |
339 void set_active_workers(uint v) { |
340 assert(v <= _total_workers, |
340 assert(v <= _total_workers, |
341 "Trying to set more workers active than there are"); |
341 "Trying to set more workers active than there are"); |
342 _active_workers = MIN2(v, _total_workers); |
342 _active_workers = MIN2(v, _total_workers); |
343 assert(v != 0, "Trying to set active workers to 0"); |
343 assert(v != 0, "Trying to set active workers to 0"); |
344 _active_workers = MAX2(1, _active_workers); |
344 _active_workers = MAX2(1U, _active_workers); |
345 assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers, |
345 assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers, |
346 "Unless dynamic should use total workers"); |
346 "Unless dynamic should use total workers"); |
347 } |
347 } |
348 virtual void run_task(AbstractGangTask* task); |
348 virtual void run_task(AbstractGangTask* task); |
349 virtual bool needs_more_workers() const { |
349 virtual bool needs_more_workers() const { |
368 // before any of them may leave. |
368 // before any of them may leave. |
369 |
369 |
370 class WorkGangBarrierSync : public StackObj { |
370 class WorkGangBarrierSync : public StackObj { |
371 protected: |
371 protected: |
372 Monitor _monitor; |
372 Monitor _monitor; |
373 int _n_workers; |
373 uint _n_workers; |
374 int _n_completed; |
374 uint _n_completed; |
375 bool _should_reset; |
375 bool _should_reset; |
376 |
376 |
377 Monitor* monitor() { return &_monitor; } |
377 Monitor* monitor() { return &_monitor; } |
378 int n_workers() { return _n_workers; } |
378 uint n_workers() { return _n_workers; } |
379 int n_completed() { return _n_completed; } |
379 uint n_completed() { return _n_completed; } |
380 bool should_reset() { return _should_reset; } |
380 bool should_reset() { return _should_reset; } |
381 |
381 |
382 void zero_completed() { _n_completed = 0; } |
382 void zero_completed() { _n_completed = 0; } |
383 void inc_completed() { _n_completed++; } |
383 void inc_completed() { _n_completed++; } |
384 |
384 |
385 void set_should_reset(bool v) { _should_reset = v; } |
385 void set_should_reset(bool v) { _should_reset = v; } |
386 |
386 |
387 public: |
387 public: |
388 WorkGangBarrierSync(); |
388 WorkGangBarrierSync(); |
389 WorkGangBarrierSync(int n_workers, const char* name); |
389 WorkGangBarrierSync(uint n_workers, const char* name); |
390 |
390 |
391 // Set the number of workers that will use the barrier. |
391 // Set the number of workers that will use the barrier. |
392 // Must be called before any of the workers start running. |
392 // Must be called before any of the workers start running. |
393 void set_n_workers(int n_workers); |
393 void set_n_workers(uint n_workers); |
394 |
394 |
395 // Enter the barrier. A worker that enters the barrier will |
395 // Enter the barrier. A worker that enters the barrier will |
396 // not be allowed to leave until all other threads have |
396 // not be allowed to leave until all other threads have |
397 // also entered the barrier. |
397 // also entered the barrier. |
398 void enter(); |
398 void enter(); |
400 |
400 |
401 // A class to manage claiming of subtasks within a group of tasks. The |
401 // A class to manage claiming of subtasks within a group of tasks. The |
402 // subtasks will be identified by integer indices, usually elements of an |
402 // subtasks will be identified by integer indices, usually elements of an |
403 // enumeration type. |
403 // enumeration type. |
404 |
404 |
405 class SubTasksDone: public CHeapObj { |
405 class SubTasksDone : public CHeapObj { |
406 jint* _tasks; |
406 uint* _tasks; |
407 int _n_tasks; |
407 uint _n_tasks; |
408 // _n_threads is used to determine when a sub task is done. |
408 // _n_threads is used to determine when a sub task is done. |
409 // It does not control how many threads will execute the subtask |
409 // It does not control how many threads will execute the subtask |
410 // but must be initialized to the number that do execute the task |
410 // but must be initialized to the number that do execute the task |
411 // in order to correctly decide when the subtask is done (all the |
411 // in order to correctly decide when the subtask is done (all the |
412 // threads working on the task have finished). |
412 // threads working on the task have finished). |
413 int _n_threads; |
413 uint _n_threads; |
414 jint _threads_completed; |
414 uint _threads_completed; |
415 #ifdef ASSERT |
415 #ifdef ASSERT |
416 volatile jint _claimed; |
416 volatile uint _claimed; |
417 #endif |
417 #endif |
418 |
418 |
419 // Set all tasks to unclaimed. |
419 // Set all tasks to unclaimed. |
420 void clear(); |
420 void clear(); |
421 |
421 |
422 public: |
422 public: |
423 // Initializes "this" to a state in which there are "n" tasks to be |
423 // Initializes "this" to a state in which there are "n" tasks to be |
424 // processed, none of the which are originally claimed. The number of |
424 // processed, none of the which are originally claimed. The number of |
425 // threads doing the tasks is initialized 1. |
425 // threads doing the tasks is initialized 1. |
426 SubTasksDone(int n); |
426 SubTasksDone(uint n); |
427 |
427 |
428 // True iff the object is in a valid state. |
428 // True iff the object is in a valid state. |
429 bool valid(); |
429 bool valid(); |
430 |
430 |
431 // Get/set the number of parallel threads doing the tasks to "t". Can only |
431 // Get/set the number of parallel threads doing the tasks to "t". Can only |
432 // be called before tasks start or after they are complete. |
432 // be called before tasks start or after they are complete. |
433 int n_threads() { return _n_threads; } |
433 uint n_threads() { return _n_threads; } |
434 void set_n_threads(int t); |
434 void set_n_threads(uint t); |
435 |
435 |
436 // Returns "false" if the task "t" is unclaimed, and ensures that task is |
436 // Returns "false" if the task "t" is unclaimed, and ensures that task is |
437 // claimed. The task "t" is required to be within the range of "this". |
437 // claimed. The task "t" is required to be within the range of "this". |
438 bool is_task_claimed(int t); |
438 bool is_task_claimed(uint t); |
439 |
439 |
440 // The calling thread asserts that it has attempted to claim all the |
440 // The calling thread asserts that it has attempted to claim all the |
441 // tasks that it will try to claim. Every thread in the parallel task |
441 // tasks that it will try to claim. Every thread in the parallel task |
442 // must execute this. (When the last thread does so, the task array is |
442 // must execute this. (When the last thread does so, the task array is |
443 // cleared.) |
443 // cleared.) |
454 // set scanning). Note that unlike the above class this is |
454 // set scanning). Note that unlike the above class this is |
455 // a stack object - is there any reason for it not to be? |
455 // a stack object - is there any reason for it not to be? |
456 |
456 |
457 class SequentialSubTasksDone : public StackObj { |
457 class SequentialSubTasksDone : public StackObj { |
458 protected: |
458 protected: |
459 jint _n_tasks; // Total number of tasks available. |
459 uint _n_tasks; // Total number of tasks available. |
460 jint _n_claimed; // Number of tasks claimed. |
460 uint _n_claimed; // Number of tasks claimed. |
461 // _n_threads is used to determine when a sub task is done. |
461 // _n_threads is used to determine when a sub task is done. |
462 // See comments on SubTasksDone::_n_threads |
462 // See comments on SubTasksDone::_n_threads |
463 jint _n_threads; // Total number of parallel threads. |
463 uint _n_threads; // Total number of parallel threads. |
464 jint _n_completed; // Number of completed threads. |
464 uint _n_completed; // Number of completed threads. |
465 |
465 |
466 void clear(); |
466 void clear(); |
467 |
467 |
468 public: |
468 public: |
469 SequentialSubTasksDone() { |
469 SequentialSubTasksDone() { |
473 |
473 |
474 // True iff the object is in a valid state. |
474 // True iff the object is in a valid state. |
475 bool valid(); |
475 bool valid(); |
476 |
476 |
477 // number of tasks |
477 // number of tasks |
478 jint n_tasks() const { return _n_tasks; } |
478 uint n_tasks() const { return _n_tasks; } |
479 |
479 |
480 // Get/set the number of parallel threads doing the tasks to t. |
480 // Get/set the number of parallel threads doing the tasks to t. |
481 // Should be called before the task starts but it is safe |
481 // Should be called before the task starts but it is safe |
482 // to call this once a task is running provided that all |
482 // to call this once a task is running provided that all |
483 // threads agree on the number of threads. |
483 // threads agree on the number of threads. |
484 int n_threads() { return _n_threads; } |
484 uint n_threads() { return _n_threads; } |
485 void set_n_threads(int t) { _n_threads = t; } |
485 void set_n_threads(uint t) { _n_threads = t; } |
486 |
486 |
487 // Set the number of tasks to be claimed to t. As above, |
487 // Set the number of tasks to be claimed to t. As above, |
488 // should be called before the tasks start but it is safe |
488 // should be called before the tasks start but it is safe |
489 // to call this once a task is running provided all threads |
489 // to call this once a task is running provided all threads |
490 // agree on the number of tasks. |
490 // agree on the number of tasks. |
491 void set_n_tasks(int t) { _n_tasks = t; } |
491 void set_n_tasks(uint t) { _n_tasks = t; } |
492 |
492 |
493 // Returns false if the next task in the sequence is unclaimed, |
493 // Returns false if the next task in the sequence is unclaimed, |
494 // and ensures that it is claimed. Will set t to be the index |
494 // and ensures that it is claimed. Will set t to be the index |
495 // of the claimed task in the sequence. Will return true if |
495 // of the claimed task in the sequence. Will return true if |
496 // the task cannot be claimed and there are none left to claim. |
496 // the task cannot be claimed and there are none left to claim. |
497 bool is_task_claimed(int& t); |
497 bool is_task_claimed(uint& t); |
498 |
498 |
499 // The calling thread asserts that it has attempted to claim |
499 // The calling thread asserts that it has attempted to claim |
500 // all the tasks it possibly can in the sequence. Every thread |
500 // all the tasks it possibly can in the sequence. Every thread |
501 // claiming tasks must promise call this. Returns true if this |
501 // claiming tasks must promise call this. Returns true if this |
502 // is the last thread to complete so that the thread can perform |
502 // is the last thread to complete so that the thread can perform |