aoqi@0: /* aoqi@0: * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_UTILITIES_WORKGROUP_HPP aoqi@0: #define SHARE_VM_UTILITIES_WORKGROUP_HPP aoqi@0: aoqi@0: #include "runtime/thread.inline.hpp" aoqi@0: #include "utilities/taskqueue.hpp" aoqi@0: aoqi@0: // Task class hierarchy: aoqi@0: // AbstractGangTask aoqi@0: // AbstractGangTaskWOopQueues aoqi@0: // aoqi@0: // Gang/Group class hierarchy: aoqi@0: // AbstractWorkGang aoqi@0: // WorkGang aoqi@0: // FlexibleWorkGang aoqi@0: // YieldingFlexibleWorkGang (defined in another file) aoqi@0: // aoqi@0: // Worker class hierarchy: aoqi@0: // GangWorker (subclass of WorkerThread) aoqi@0: // YieldingFlexibleGangWorker (defined in another file) aoqi@0: aoqi@0: // Forward declarations of classes defined here aoqi@0: aoqi@0: class WorkGang; aoqi@0: class GangWorker; aoqi@0: class YieldingFlexibleGangWorker; aoqi@0: class YieldingFlexibleGangTask; aoqi@0: class WorkData; aoqi@0: class AbstractWorkGang; aoqi@0: aoqi@0: // An abstract task to be worked on by a gang. aoqi@0: // You subclass this to supply your own work() method aoqi@0: class AbstractGangTask VALUE_OBJ_CLASS_SPEC { aoqi@0: public: aoqi@0: // The abstract work method. aoqi@0: // The argument tells you which member of the gang you are. aoqi@0: virtual void work(uint worker_id) = 0; aoqi@0: aoqi@0: // This method configures the task for proper termination. aoqi@0: // Some tasks do not have any requirements on termination aoqi@0: // and may inherit this method that does nothing. Some aoqi@0: // tasks do some coordination on termination and override aoqi@0: // this method to implement that coordination. aoqi@0: virtual void set_for_termination(int active_workers) {}; aoqi@0: aoqi@0: // Debugging accessor for the name. aoqi@0: const char* name() const PRODUCT_RETURN_(return NULL;); aoqi@0: int counter() { return _counter; } aoqi@0: void set_counter(int value) { _counter = value; } aoqi@0: int *address_of_counter() { return &_counter; } aoqi@0: aoqi@0: // RTTI aoqi@0: NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const { aoqi@0: return false; aoqi@0: }) aoqi@0: aoqi@0: private: aoqi@0: NOT_PRODUCT(const char* _name;) aoqi@0: // ??? Should a task have a priority associated with it? aoqi@0: // ??? Or can the run method adjust priority as needed? aoqi@0: int _counter; aoqi@0: aoqi@0: protected: aoqi@0: // Constructor and desctructor: only construct subclasses. aoqi@0: AbstractGangTask(const char* name) aoqi@0: { aoqi@0: NOT_PRODUCT(_name = name); aoqi@0: _counter = 0; aoqi@0: } aoqi@0: ~AbstractGangTask() { } aoqi@0: aoqi@0: public: aoqi@0: }; aoqi@0: aoqi@0: class AbstractGangTaskWOopQueues : public AbstractGangTask { aoqi@0: OopTaskQueueSet* _queues; aoqi@0: ParallelTaskTerminator _terminator; aoqi@0: public: aoqi@0: AbstractGangTaskWOopQueues(const char* name, OopTaskQueueSet* queues) : aoqi@0: AbstractGangTask(name), _queues(queues), _terminator(0, _queues) {} aoqi@0: ParallelTaskTerminator* terminator() { return &_terminator; } aoqi@0: virtual void set_for_termination(int active_workers) { aoqi@0: terminator()->reset_for_reuse(active_workers); aoqi@0: } aoqi@0: OopTaskQueueSet* queues() { return _queues; } aoqi@0: }; aoqi@0: aoqi@0: aoqi@0: // Class AbstractWorkGang: aoqi@0: // An abstract class representing a gang of workers. aoqi@0: // You subclass this to supply an implementation of run_task(). aoqi@0: class AbstractWorkGang: public CHeapObj { aoqi@0: // Here's the public interface to this class. aoqi@0: public: aoqi@0: // Constructor and destructor. aoqi@0: AbstractWorkGang(const char* name, bool are_GC_task_threads, aoqi@0: bool are_ConcurrentGC_threads); aoqi@0: ~AbstractWorkGang(); aoqi@0: // Run a task, returns when the task is done (or terminated). aoqi@0: virtual void run_task(AbstractGangTask* task) = 0; aoqi@0: // Stop and terminate all workers. aoqi@0: virtual void stop(); aoqi@0: // Return true if more workers should be applied to the task. aoqi@0: virtual bool needs_more_workers() const { return true; } aoqi@0: public: aoqi@0: // Debugging. aoqi@0: const char* name() const; aoqi@0: protected: aoqi@0: // Initialize only instance data. aoqi@0: const bool _are_GC_task_threads; aoqi@0: const bool _are_ConcurrentGC_threads; aoqi@0: // Printing support. aoqi@0: const char* _name; aoqi@0: // The monitor which protects these data, aoqi@0: // and notifies of changes in it. aoqi@0: Monitor* _monitor; aoqi@0: // The count of the number of workers in the gang. aoqi@0: uint _total_workers; aoqi@0: // Whether the workers should terminate. aoqi@0: bool _terminate; aoqi@0: // The array of worker threads for this gang. aoqi@0: // This is only needed for cleaning up. aoqi@0: GangWorker** _gang_workers; aoqi@0: // The task for this gang. aoqi@0: AbstractGangTask* _task; aoqi@0: // A sequence number for the current task. aoqi@0: int _sequence_number; aoqi@0: // The number of started workers. aoqi@0: uint _started_workers; aoqi@0: // The number of finished workers. aoqi@0: uint _finished_workers; aoqi@0: public: aoqi@0: // Accessors for fields aoqi@0: Monitor* monitor() const { aoqi@0: return _monitor; aoqi@0: } aoqi@0: uint total_workers() const { aoqi@0: return _total_workers; aoqi@0: } aoqi@0: virtual uint active_workers() const { aoqi@0: return _total_workers; aoqi@0: } aoqi@0: bool terminate() const { aoqi@0: return _terminate; aoqi@0: } aoqi@0: GangWorker** gang_workers() const { aoqi@0: return _gang_workers; aoqi@0: } aoqi@0: AbstractGangTask* task() const { aoqi@0: return _task; aoqi@0: } aoqi@0: int sequence_number() const { aoqi@0: return _sequence_number; aoqi@0: } aoqi@0: uint started_workers() const { aoqi@0: return _started_workers; aoqi@0: } aoqi@0: uint finished_workers() const { aoqi@0: return _finished_workers; aoqi@0: } aoqi@0: bool are_GC_task_threads() const { aoqi@0: return _are_GC_task_threads; aoqi@0: } aoqi@0: bool are_ConcurrentGC_threads() const { aoqi@0: return _are_ConcurrentGC_threads; aoqi@0: } aoqi@0: // Predicates. aoqi@0: bool is_idle() const { aoqi@0: return (task() == NULL); aoqi@0: } aoqi@0: // Return the Ith gang worker. aoqi@0: GangWorker* gang_worker(uint i) const; aoqi@0: aoqi@0: void threads_do(ThreadClosure* tc) const; aoqi@0: aoqi@0: // Printing aoqi@0: void print_worker_threads_on(outputStream *st) const; aoqi@0: void print_worker_threads() const { aoqi@0: print_worker_threads_on(tty); aoqi@0: } aoqi@0: aoqi@0: protected: aoqi@0: friend class GangWorker; aoqi@0: friend class YieldingFlexibleGangWorker; aoqi@0: // Note activation and deactivation of workers. aoqi@0: // These methods should only be called with the mutex held. aoqi@0: void internal_worker_poll(WorkData* data) const; aoqi@0: void internal_note_start(); aoqi@0: void internal_note_finish(); aoqi@0: }; aoqi@0: aoqi@0: class WorkData: public StackObj { aoqi@0: // This would be a struct, but I want accessor methods. aoqi@0: private: aoqi@0: bool _terminate; aoqi@0: AbstractGangTask* _task; aoqi@0: int _sequence_number; aoqi@0: public: aoqi@0: // Constructor and destructor aoqi@0: WorkData() { aoqi@0: _terminate = false; aoqi@0: _task = NULL; aoqi@0: _sequence_number = 0; aoqi@0: } aoqi@0: ~WorkData() { aoqi@0: } aoqi@0: // Accessors and modifiers aoqi@0: bool terminate() const { return _terminate; } aoqi@0: void set_terminate(bool value) { _terminate = value; } aoqi@0: AbstractGangTask* task() const { return _task; } aoqi@0: void set_task(AbstractGangTask* value) { _task = value; } aoqi@0: int sequence_number() const { return _sequence_number; } aoqi@0: void set_sequence_number(int value) { _sequence_number = value; } aoqi@0: aoqi@0: YieldingFlexibleGangTask* yf_task() const { aoqi@0: return (YieldingFlexibleGangTask*)_task; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: // Class WorkGang: aoqi@0: class WorkGang: public AbstractWorkGang { aoqi@0: public: aoqi@0: // Constructor aoqi@0: WorkGang(const char* name, uint workers, aoqi@0: bool are_GC_task_threads, bool are_ConcurrentGC_threads); aoqi@0: // Run a task, returns when the task is done (or terminated). aoqi@0: virtual void run_task(AbstractGangTask* task); aoqi@0: void run_task(AbstractGangTask* task, uint no_of_parallel_workers); aoqi@0: // Allocate a worker and return a pointer to it. aoqi@0: virtual GangWorker* allocate_worker(uint which); aoqi@0: // Initialize workers in the gang. Return true if initialization aoqi@0: // succeeded. The type of the worker can be overridden in a derived aoqi@0: // class with the appropriate implementation of allocate_worker(). aoqi@0: bool initialize_workers(); aoqi@0: }; aoqi@0: aoqi@0: // Class GangWorker: aoqi@0: // Several instances of this class run in parallel as workers for a gang. aoqi@0: class GangWorker: public WorkerThread { aoqi@0: public: aoqi@0: // Constructors and destructor. aoqi@0: GangWorker(AbstractWorkGang* gang, uint id); aoqi@0: aoqi@0: // The only real method: run a task for the gang. aoqi@0: virtual void run(); aoqi@0: // Predicate for Thread aoqi@0: virtual bool is_GC_task_thread() const; aoqi@0: virtual bool is_ConcurrentGC_thread() const; aoqi@0: // Printing aoqi@0: void print_on(outputStream* st) const; aoqi@0: virtual void print() const { print_on(tty); } aoqi@0: protected: aoqi@0: AbstractWorkGang* _gang; aoqi@0: aoqi@0: virtual void initialize(); aoqi@0: virtual void loop(); aoqi@0: aoqi@0: public: aoqi@0: AbstractWorkGang* gang() const { return _gang; } aoqi@0: }; aoqi@0: aoqi@0: // Dynamic number of worker threads aoqi@0: // aoqi@0: // This type of work gang is used to run different numbers of aoqi@0: // worker threads at different times. The aoqi@0: // number of workers run for a task is "_active_workers" aoqi@0: // instead of "_total_workers" in a WorkGang. The method aoqi@0: // "needs_more_workers()" returns true until "_active_workers" aoqi@0: // have been started and returns false afterwards. The aoqi@0: // implementation of "needs_more_workers()" in WorkGang always aoqi@0: // returns true so that all workers are started. The method aoqi@0: // "loop()" in GangWorker was modified to ask "needs_more_workers()" aoqi@0: // in its loop to decide if it should start working on a task. aoqi@0: // A worker in "loop()" waits for notification on the WorkGang aoqi@0: // monitor and execution of each worker as it checks for work aoqi@0: // is serialized via the same monitor. The "needs_more_workers()" aoqi@0: // call is serialized and additionally the calculation for the aoqi@0: // "part" (effectively the worker id for executing the task) is aoqi@0: // serialized to give each worker a unique "part". Workers that aoqi@0: // are not needed for this tasks (i.e., "_active_workers" have aoqi@0: // been started before it, continue to wait for work. aoqi@0: aoqi@0: class FlexibleWorkGang: public WorkGang { aoqi@0: // The currently active workers in this gang. aoqi@0: // This is a number that is dynamically adjusted aoqi@0: // and checked in the run_task() method at each invocation. aoqi@0: // As described above _active_workers determines the number aoqi@0: // of threads started on a task. It must also be used to aoqi@0: // determine completion. aoqi@0: aoqi@0: protected: aoqi@0: uint _active_workers; aoqi@0: public: aoqi@0: // Constructor and destructor. aoqi@0: // Initialize active_workers to a minimum value. Setting it to aoqi@0: // the parameter "workers" will initialize it to a maximum aoqi@0: // value which is not desirable. aoqi@0: FlexibleWorkGang(const char* name, uint workers, aoqi@0: bool are_GC_task_threads, aoqi@0: bool are_ConcurrentGC_threads) : aoqi@0: WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads), aoqi@0: _active_workers(UseDynamicNumberOfGCThreads ? 1U : ParallelGCThreads) {} aoqi@0: // Accessors for fields aoqi@0: virtual uint active_workers() const { return _active_workers; } aoqi@0: void set_active_workers(uint v) { aoqi@0: assert(v <= _total_workers, aoqi@0: "Trying to set more workers active than there are"); aoqi@0: _active_workers = MIN2(v, _total_workers); aoqi@0: assert(v != 0, "Trying to set active workers to 0"); aoqi@0: _active_workers = MAX2(1U, _active_workers); aoqi@0: assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers, aoqi@0: "Unless dynamic should use total workers"); aoqi@0: } aoqi@0: virtual void run_task(AbstractGangTask* task); aoqi@0: virtual bool needs_more_workers() const { aoqi@0: return _started_workers < _active_workers; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: // Work gangs in garbage collectors: 2009-06-10 aoqi@0: // aoqi@0: // SharedHeap - work gang for stop-the-world parallel collection. aoqi@0: // Used by aoqi@0: // ParNewGeneration aoqi@0: // CMSParRemarkTask aoqi@0: // CMSRefProcTaskExecutor aoqi@0: // G1CollectedHeap aoqi@0: // G1ParFinalCountTask aoqi@0: // ConcurrentMark aoqi@0: // CMSCollector aoqi@0: aoqi@0: // A class that acts as a synchronisation barrier. Workers enter aoqi@0: // the barrier and must wait until all other workers have entered aoqi@0: // before any of them may leave. aoqi@0: aoqi@0: class WorkGangBarrierSync : public StackObj { aoqi@0: protected: aoqi@0: Monitor _monitor; aoqi@0: uint _n_workers; aoqi@0: uint _n_completed; aoqi@0: bool _should_reset; aoqi@0: bool _aborted; aoqi@0: aoqi@0: Monitor* monitor() { return &_monitor; } aoqi@0: uint n_workers() { return _n_workers; } aoqi@0: uint n_completed() { return _n_completed; } aoqi@0: bool should_reset() { return _should_reset; } aoqi@0: bool aborted() { return _aborted; } aoqi@0: aoqi@0: void zero_completed() { _n_completed = 0; } aoqi@0: void inc_completed() { _n_completed++; } aoqi@0: void set_aborted() { _aborted = true; } aoqi@0: void set_should_reset(bool v) { _should_reset = v; } aoqi@0: aoqi@0: public: aoqi@0: WorkGangBarrierSync(); aoqi@0: WorkGangBarrierSync(uint n_workers, const char* name); aoqi@0: aoqi@0: // Set the number of workers that will use the barrier. aoqi@0: // Must be called before any of the workers start running. aoqi@0: void set_n_workers(uint n_workers); aoqi@0: aoqi@0: // Enter the barrier. A worker that enters the barrier will aoqi@0: // not be allowed to leave until all other threads have aoqi@0: // also entered the barrier or the barrier is aborted. aoqi@0: // Returns false if the barrier was aborted. aoqi@0: bool enter(); aoqi@0: aoqi@0: // Aborts the barrier and wakes up any threads waiting for aoqi@0: // the barrier to complete. The barrier will remain in the aoqi@0: // aborted state until the next call to set_n_workers(). aoqi@0: void abort(); aoqi@0: }; aoqi@0: aoqi@0: // A class to manage claiming of subtasks within a group of tasks. The aoqi@0: // subtasks will be identified by integer indices, usually elements of an aoqi@0: // enumeration type. aoqi@0: aoqi@0: class SubTasksDone: public CHeapObj { aoqi@0: uint* _tasks; aoqi@0: uint _n_tasks; aoqi@0: // _n_threads is used to determine when a sub task is done. aoqi@0: // It does not control how many threads will execute the subtask aoqi@0: // but must be initialized to the number that do execute the task aoqi@0: // in order to correctly decide when the subtask is done (all the aoqi@0: // threads working on the task have finished). aoqi@0: uint _n_threads; aoqi@0: uint _threads_completed; aoqi@0: #ifdef ASSERT aoqi@0: volatile uint _claimed; aoqi@0: #endif aoqi@0: aoqi@0: // Set all tasks to unclaimed. aoqi@0: void clear(); aoqi@0: aoqi@0: public: aoqi@0: // Initializes "this" to a state in which there are "n" tasks to be aoqi@0: // processed, none of the which are originally claimed. The number of aoqi@0: // threads doing the tasks is initialized 1. aoqi@0: SubTasksDone(uint n); aoqi@0: aoqi@0: // True iff the object is in a valid state. aoqi@0: bool valid(); aoqi@0: aoqi@0: // Get/set the number of parallel threads doing the tasks to "t". Can only aoqi@0: // be called before tasks start or after they are complete. aoqi@0: uint n_threads() { return _n_threads; } aoqi@0: void set_n_threads(uint t); aoqi@0: aoqi@0: // Returns "false" if the task "t" is unclaimed, and ensures that task is aoqi@0: // claimed. The task "t" is required to be within the range of "this". aoqi@0: bool is_task_claimed(uint t); aoqi@0: aoqi@0: // The calling thread asserts that it has attempted to claim all the aoqi@0: // tasks that it will try to claim. Every thread in the parallel task aoqi@0: // must execute this. (When the last thread does so, the task array is aoqi@0: // cleared.) aoqi@0: void all_tasks_completed(); aoqi@0: aoqi@0: // Destructor. aoqi@0: ~SubTasksDone(); aoqi@0: }; aoqi@0: aoqi@0: // As above, but for sequential tasks, i.e. instead of claiming aoqi@0: // sub-tasks from a set (possibly an enumeration), claim sub-tasks aoqi@0: // in sequential order. This is ideal for claiming dynamically aoqi@0: // partitioned tasks (like striding in the parallel remembered aoqi@0: // set scanning). Note that unlike the above class this is aoqi@0: // a stack object - is there any reason for it not to be? aoqi@0: aoqi@0: class SequentialSubTasksDone : public StackObj { aoqi@0: protected: aoqi@0: uint _n_tasks; // Total number of tasks available. aoqi@0: uint _n_claimed; // Number of tasks claimed. aoqi@0: // _n_threads is used to determine when a sub task is done. aoqi@0: // See comments on SubTasksDone::_n_threads aoqi@0: uint _n_threads; // Total number of parallel threads. aoqi@0: uint _n_completed; // Number of completed threads. aoqi@0: aoqi@0: void clear(); aoqi@0: aoqi@0: public: aoqi@0: SequentialSubTasksDone() { aoqi@0: clear(); aoqi@0: } aoqi@0: ~SequentialSubTasksDone() {} aoqi@0: aoqi@0: // True iff the object is in a valid state. aoqi@0: bool valid(); aoqi@0: aoqi@0: // number of tasks aoqi@0: uint n_tasks() const { return _n_tasks; } aoqi@0: aoqi@0: // Get/set the number of parallel threads doing the tasks to t. aoqi@0: // Should be called before the task starts but it is safe aoqi@0: // to call this once a task is running provided that all aoqi@0: // threads agree on the number of threads. aoqi@0: uint n_threads() { return _n_threads; } aoqi@0: void set_n_threads(uint t) { _n_threads = t; } aoqi@0: aoqi@0: // Set the number of tasks to be claimed to t. As above, aoqi@0: // should be called before the tasks start but it is safe aoqi@0: // to call this once a task is running provided all threads aoqi@0: // agree on the number of tasks. aoqi@0: void set_n_tasks(uint t) { _n_tasks = t; } aoqi@0: aoqi@0: // Returns false if the next task in the sequence is unclaimed, aoqi@0: // and ensures that it is claimed. Will set t to be the index aoqi@0: // of the claimed task in the sequence. Will return true if aoqi@0: // the task cannot be claimed and there are none left to claim. aoqi@0: bool is_task_claimed(uint& t); aoqi@0: aoqi@0: // The calling thread asserts that it has attempted to claim aoqi@0: // all the tasks it possibly can in the sequence. Every thread aoqi@0: // claiming tasks must promise call this. Returns true if this aoqi@0: // is the last thread to complete so that the thread can perform aoqi@0: // cleanup if necessary. aoqi@0: bool all_tasks_completed(); aoqi@0: }; aoqi@0: aoqi@0: // Represents a set of free small integer ids. aoqi@0: class FreeIdSet : public CHeapObj { aoqi@0: enum { aoqi@0: end_of_list = -1, aoqi@0: claimed = -2 aoqi@0: }; aoqi@0: aoqi@0: int _sz; aoqi@0: Monitor* _mon; aoqi@0: aoqi@0: int* _ids; aoqi@0: int _hd; aoqi@0: int _waiters; aoqi@0: int _claimed; aoqi@0: aoqi@0: static bool _safepoint; aoqi@0: typedef FreeIdSet* FreeIdSetPtr; aoqi@0: static const int NSets = 10; aoqi@0: static FreeIdSetPtr _sets[NSets]; aoqi@0: static bool _stat_init; aoqi@0: int _index; aoqi@0: aoqi@0: public: aoqi@0: FreeIdSet(int sz, Monitor* mon); aoqi@0: ~FreeIdSet(); aoqi@0: aoqi@0: static void set_safepoint(bool b); aoqi@0: aoqi@0: // Attempt to claim the given id permanently. Returns "true" iff aoqi@0: // successful. aoqi@0: bool claim_perm_id(int i); aoqi@0: aoqi@0: // Returns an unclaimed parallel id (waiting for one to be released if aoqi@0: // necessary). Returns "-1" if a GC wakes up a wait for an id. aoqi@0: int claim_par_id(); aoqi@0: aoqi@0: void release_par_id(int id); aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_UTILITIES_WORKGROUP_HPP