1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/vm/utilities/workgroup.hpp Wed Apr 27 01:25:04 2016 +0800 1.3 @@ -0,0 +1,543 @@ 1.4 +/* 1.5 + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + * 1.26 + */ 1.27 + 1.28 +#ifndef SHARE_VM_UTILITIES_WORKGROUP_HPP 1.29 +#define SHARE_VM_UTILITIES_WORKGROUP_HPP 1.30 + 1.31 +#include "runtime/thread.inline.hpp" 1.32 +#include "utilities/taskqueue.hpp" 1.33 + 1.34 +// Task class hierarchy: 1.35 +// AbstractGangTask 1.36 +// AbstractGangTaskWOopQueues 1.37 +// 1.38 +// Gang/Group class hierarchy: 1.39 +// AbstractWorkGang 1.40 +// WorkGang 1.41 +// FlexibleWorkGang 1.42 +// YieldingFlexibleWorkGang (defined in another file) 1.43 +// 1.44 +// Worker class hierarchy: 1.45 +// GangWorker (subclass of WorkerThread) 1.46 +// YieldingFlexibleGangWorker (defined in another file) 1.47 + 1.48 +// Forward declarations of classes defined here 1.49 + 1.50 +class WorkGang; 1.51 +class GangWorker; 1.52 +class YieldingFlexibleGangWorker; 1.53 +class YieldingFlexibleGangTask; 1.54 +class WorkData; 1.55 +class AbstractWorkGang; 1.56 + 1.57 +// An abstract task to be worked on by a gang. 1.58 +// You subclass this to supply your own work() method 1.59 +class AbstractGangTask VALUE_OBJ_CLASS_SPEC { 1.60 +public: 1.61 + // The abstract work method. 1.62 + // The argument tells you which member of the gang you are. 1.63 + virtual void work(uint worker_id) = 0; 1.64 + 1.65 + // This method configures the task for proper termination. 1.66 + // Some tasks do not have any requirements on termination 1.67 + // and may inherit this method that does nothing. Some 1.68 + // tasks do some coordination on termination and override 1.69 + // this method to implement that coordination. 1.70 + virtual void set_for_termination(int active_workers) {}; 1.71 + 1.72 + // Debugging accessor for the name. 1.73 + const char* name() const PRODUCT_RETURN_(return NULL;); 1.74 + int counter() { return _counter; } 1.75 + void set_counter(int value) { _counter = value; } 1.76 + int *address_of_counter() { return &_counter; } 1.77 + 1.78 + // RTTI 1.79 + NOT_PRODUCT(virtual bool is_YieldingFlexibleGang_task() const { 1.80 + return false; 1.81 + }) 1.82 + 1.83 +private: 1.84 + NOT_PRODUCT(const char* _name;) 1.85 + // ??? Should a task have a priority associated with it? 1.86 + // ??? Or can the run method adjust priority as needed? 1.87 + int _counter; 1.88 + 1.89 +protected: 1.90 + // Constructor and desctructor: only construct subclasses. 1.91 + AbstractGangTask(const char* name) 1.92 + { 1.93 + NOT_PRODUCT(_name = name); 1.94 + _counter = 0; 1.95 + } 1.96 + ~AbstractGangTask() { } 1.97 + 1.98 +public: 1.99 +}; 1.100 + 1.101 +class AbstractGangTaskWOopQueues : public AbstractGangTask { 1.102 + OopTaskQueueSet* _queues; 1.103 + ParallelTaskTerminator _terminator; 1.104 + public: 1.105 + AbstractGangTaskWOopQueues(const char* name, OopTaskQueueSet* queues) : 1.106 + AbstractGangTask(name), _queues(queues), _terminator(0, _queues) {} 1.107 + ParallelTaskTerminator* terminator() { return &_terminator; } 1.108 + virtual void set_for_termination(int active_workers) { 1.109 + terminator()->reset_for_reuse(active_workers); 1.110 + } 1.111 + OopTaskQueueSet* queues() { return _queues; } 1.112 +}; 1.113 + 1.114 + 1.115 +// Class AbstractWorkGang: 1.116 +// An abstract class representing a gang of workers. 1.117 +// You subclass this to supply an implementation of run_task(). 1.118 +class AbstractWorkGang: public CHeapObj<mtInternal> { 1.119 + // Here's the public interface to this class. 1.120 +public: 1.121 + // Constructor and destructor. 1.122 + AbstractWorkGang(const char* name, bool are_GC_task_threads, 1.123 + bool are_ConcurrentGC_threads); 1.124 + ~AbstractWorkGang(); 1.125 + // Run a task, returns when the task is done (or terminated). 1.126 + virtual void run_task(AbstractGangTask* task) = 0; 1.127 + // Stop and terminate all workers. 1.128 + virtual void stop(); 1.129 + // Return true if more workers should be applied to the task. 1.130 + virtual bool needs_more_workers() const { return true; } 1.131 +public: 1.132 + // Debugging. 1.133 + const char* name() const; 1.134 +protected: 1.135 + // Initialize only instance data. 1.136 + const bool _are_GC_task_threads; 1.137 + const bool _are_ConcurrentGC_threads; 1.138 + // Printing support. 1.139 + const char* _name; 1.140 + // The monitor which protects these data, 1.141 + // and notifies of changes in it. 1.142 + Monitor* _monitor; 1.143 + // The count of the number of workers in the gang. 1.144 + uint _total_workers; 1.145 + // Whether the workers should terminate. 1.146 + bool _terminate; 1.147 + // The array of worker threads for this gang. 1.148 + // This is only needed for cleaning up. 1.149 + GangWorker** _gang_workers; 1.150 + // The task for this gang. 1.151 + AbstractGangTask* _task; 1.152 + // A sequence number for the current task. 1.153 + int _sequence_number; 1.154 + // The number of started workers. 1.155 + uint _started_workers; 1.156 + // The number of finished workers. 1.157 + uint _finished_workers; 1.158 +public: 1.159 + // Accessors for fields 1.160 + Monitor* monitor() const { 1.161 + return _monitor; 1.162 + } 1.163 + uint total_workers() const { 1.164 + return _total_workers; 1.165 + } 1.166 + virtual uint active_workers() const { 1.167 + return _total_workers; 1.168 + } 1.169 + bool terminate() const { 1.170 + return _terminate; 1.171 + } 1.172 + GangWorker** gang_workers() const { 1.173 + return _gang_workers; 1.174 + } 1.175 + AbstractGangTask* task() const { 1.176 + return _task; 1.177 + } 1.178 + int sequence_number() const { 1.179 + return _sequence_number; 1.180 + } 1.181 + uint started_workers() const { 1.182 + return _started_workers; 1.183 + } 1.184 + uint finished_workers() const { 1.185 + return _finished_workers; 1.186 + } 1.187 + bool are_GC_task_threads() const { 1.188 + return _are_GC_task_threads; 1.189 + } 1.190 + bool are_ConcurrentGC_threads() const { 1.191 + return _are_ConcurrentGC_threads; 1.192 + } 1.193 + // Predicates. 1.194 + bool is_idle() const { 1.195 + return (task() == NULL); 1.196 + } 1.197 + // Return the Ith gang worker. 1.198 + GangWorker* gang_worker(uint i) const; 1.199 + 1.200 + void threads_do(ThreadClosure* tc) const; 1.201 + 1.202 + // Printing 1.203 + void print_worker_threads_on(outputStream *st) const; 1.204 + void print_worker_threads() const { 1.205 + print_worker_threads_on(tty); 1.206 + } 1.207 + 1.208 +protected: 1.209 + friend class GangWorker; 1.210 + friend class YieldingFlexibleGangWorker; 1.211 + // Note activation and deactivation of workers. 1.212 + // These methods should only be called with the mutex held. 1.213 + void internal_worker_poll(WorkData* data) const; 1.214 + void internal_note_start(); 1.215 + void internal_note_finish(); 1.216 +}; 1.217 + 1.218 +class WorkData: public StackObj { 1.219 + // This would be a struct, but I want accessor methods. 1.220 +private: 1.221 + bool _terminate; 1.222 + AbstractGangTask* _task; 1.223 + int _sequence_number; 1.224 +public: 1.225 + // Constructor and destructor 1.226 + WorkData() { 1.227 + _terminate = false; 1.228 + _task = NULL; 1.229 + _sequence_number = 0; 1.230 + } 1.231 + ~WorkData() { 1.232 + } 1.233 + // Accessors and modifiers 1.234 + bool terminate() const { return _terminate; } 1.235 + void set_terminate(bool value) { _terminate = value; } 1.236 + AbstractGangTask* task() const { return _task; } 1.237 + void set_task(AbstractGangTask* value) { _task = value; } 1.238 + int sequence_number() const { return _sequence_number; } 1.239 + void set_sequence_number(int value) { _sequence_number = value; } 1.240 + 1.241 + YieldingFlexibleGangTask* yf_task() const { 1.242 + return (YieldingFlexibleGangTask*)_task; 1.243 + } 1.244 +}; 1.245 + 1.246 +// Class WorkGang: 1.247 +class WorkGang: public AbstractWorkGang { 1.248 +public: 1.249 + // Constructor 1.250 + WorkGang(const char* name, uint workers, 1.251 + bool are_GC_task_threads, bool are_ConcurrentGC_threads); 1.252 + // Run a task, returns when the task is done (or terminated). 1.253 + virtual void run_task(AbstractGangTask* task); 1.254 + void run_task(AbstractGangTask* task, uint no_of_parallel_workers); 1.255 + // Allocate a worker and return a pointer to it. 1.256 + virtual GangWorker* allocate_worker(uint which); 1.257 + // Initialize workers in the gang. Return true if initialization 1.258 + // succeeded. The type of the worker can be overridden in a derived 1.259 + // class with the appropriate implementation of allocate_worker(). 1.260 + bool initialize_workers(); 1.261 +}; 1.262 + 1.263 +// Class GangWorker: 1.264 +// Several instances of this class run in parallel as workers for a gang. 1.265 +class GangWorker: public WorkerThread { 1.266 +public: 1.267 + // Constructors and destructor. 1.268 + GangWorker(AbstractWorkGang* gang, uint id); 1.269 + 1.270 + // The only real method: run a task for the gang. 1.271 + virtual void run(); 1.272 + // Predicate for Thread 1.273 + virtual bool is_GC_task_thread() const; 1.274 + virtual bool is_ConcurrentGC_thread() const; 1.275 + // Printing 1.276 + void print_on(outputStream* st) const; 1.277 + virtual void print() const { print_on(tty); } 1.278 +protected: 1.279 + AbstractWorkGang* _gang; 1.280 + 1.281 + virtual void initialize(); 1.282 + virtual void loop(); 1.283 + 1.284 +public: 1.285 + AbstractWorkGang* gang() const { return _gang; } 1.286 +}; 1.287 + 1.288 +// Dynamic number of worker threads 1.289 +// 1.290 +// This type of work gang is used to run different numbers of 1.291 +// worker threads at different times. The 1.292 +// number of workers run for a task is "_active_workers" 1.293 +// instead of "_total_workers" in a WorkGang. The method 1.294 +// "needs_more_workers()" returns true until "_active_workers" 1.295 +// have been started and returns false afterwards. The 1.296 +// implementation of "needs_more_workers()" in WorkGang always 1.297 +// returns true so that all workers are started. The method 1.298 +// "loop()" in GangWorker was modified to ask "needs_more_workers()" 1.299 +// in its loop to decide if it should start working on a task. 1.300 +// A worker in "loop()" waits for notification on the WorkGang 1.301 +// monitor and execution of each worker as it checks for work 1.302 +// is serialized via the same monitor. The "needs_more_workers()" 1.303 +// call is serialized and additionally the calculation for the 1.304 +// "part" (effectively the worker id for executing the task) is 1.305 +// serialized to give each worker a unique "part". Workers that 1.306 +// are not needed for this tasks (i.e., "_active_workers" have 1.307 +// been started before it, continue to wait for work. 1.308 + 1.309 +class FlexibleWorkGang: public WorkGang { 1.310 + // The currently active workers in this gang. 1.311 + // This is a number that is dynamically adjusted 1.312 + // and checked in the run_task() method at each invocation. 1.313 + // As described above _active_workers determines the number 1.314 + // of threads started on a task. It must also be used to 1.315 + // determine completion. 1.316 + 1.317 + protected: 1.318 + uint _active_workers; 1.319 + public: 1.320 + // Constructor and destructor. 1.321 + // Initialize active_workers to a minimum value. Setting it to 1.322 + // the parameter "workers" will initialize it to a maximum 1.323 + // value which is not desirable. 1.324 + FlexibleWorkGang(const char* name, uint workers, 1.325 + bool are_GC_task_threads, 1.326 + bool are_ConcurrentGC_threads) : 1.327 + WorkGang(name, workers, are_GC_task_threads, are_ConcurrentGC_threads), 1.328 + _active_workers(UseDynamicNumberOfGCThreads ? 1U : ParallelGCThreads) {} 1.329 + // Accessors for fields 1.330 + virtual uint active_workers() const { return _active_workers; } 1.331 + void set_active_workers(uint v) { 1.332 + assert(v <= _total_workers, 1.333 + "Trying to set more workers active than there are"); 1.334 + _active_workers = MIN2(v, _total_workers); 1.335 + assert(v != 0, "Trying to set active workers to 0"); 1.336 + _active_workers = MAX2(1U, _active_workers); 1.337 + assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers, 1.338 + "Unless dynamic should use total workers"); 1.339 + } 1.340 + virtual void run_task(AbstractGangTask* task); 1.341 + virtual bool needs_more_workers() const { 1.342 + return _started_workers < _active_workers; 1.343 + } 1.344 +}; 1.345 + 1.346 +// Work gangs in garbage collectors: 2009-06-10 1.347 +// 1.348 +// SharedHeap - work gang for stop-the-world parallel collection. 1.349 +// Used by 1.350 +// ParNewGeneration 1.351 +// CMSParRemarkTask 1.352 +// CMSRefProcTaskExecutor 1.353 +// G1CollectedHeap 1.354 +// G1ParFinalCountTask 1.355 +// ConcurrentMark 1.356 +// CMSCollector 1.357 + 1.358 +// A class that acts as a synchronisation barrier. Workers enter 1.359 +// the barrier and must wait until all other workers have entered 1.360 +// before any of them may leave. 1.361 + 1.362 +class WorkGangBarrierSync : public StackObj { 1.363 +protected: 1.364 + Monitor _monitor; 1.365 + uint _n_workers; 1.366 + uint _n_completed; 1.367 + bool _should_reset; 1.368 + bool _aborted; 1.369 + 1.370 + Monitor* monitor() { return &_monitor; } 1.371 + uint n_workers() { return _n_workers; } 1.372 + uint n_completed() { return _n_completed; } 1.373 + bool should_reset() { return _should_reset; } 1.374 + bool aborted() { return _aborted; } 1.375 + 1.376 + void zero_completed() { _n_completed = 0; } 1.377 + void inc_completed() { _n_completed++; } 1.378 + void set_aborted() { _aborted = true; } 1.379 + void set_should_reset(bool v) { _should_reset = v; } 1.380 + 1.381 +public: 1.382 + WorkGangBarrierSync(); 1.383 + WorkGangBarrierSync(uint n_workers, const char* name); 1.384 + 1.385 + // Set the number of workers that will use the barrier. 1.386 + // Must be called before any of the workers start running. 1.387 + void set_n_workers(uint n_workers); 1.388 + 1.389 + // Enter the barrier. A worker that enters the barrier will 1.390 + // not be allowed to leave until all other threads have 1.391 + // also entered the barrier or the barrier is aborted. 1.392 + // Returns false if the barrier was aborted. 1.393 + bool enter(); 1.394 + 1.395 + // Aborts the barrier and wakes up any threads waiting for 1.396 + // the barrier to complete. The barrier will remain in the 1.397 + // aborted state until the next call to set_n_workers(). 1.398 + void abort(); 1.399 +}; 1.400 + 1.401 +// A class to manage claiming of subtasks within a group of tasks. The 1.402 +// subtasks will be identified by integer indices, usually elements of an 1.403 +// enumeration type. 1.404 + 1.405 +class SubTasksDone: public CHeapObj<mtInternal> { 1.406 + uint* _tasks; 1.407 + uint _n_tasks; 1.408 + // _n_threads is used to determine when a sub task is done. 1.409 + // It does not control how many threads will execute the subtask 1.410 + // but must be initialized to the number that do execute the task 1.411 + // in order to correctly decide when the subtask is done (all the 1.412 + // threads working on the task have finished). 1.413 + uint _n_threads; 1.414 + uint _threads_completed; 1.415 +#ifdef ASSERT 1.416 + volatile uint _claimed; 1.417 +#endif 1.418 + 1.419 + // Set all tasks to unclaimed. 1.420 + void clear(); 1.421 + 1.422 +public: 1.423 + // Initializes "this" to a state in which there are "n" tasks to be 1.424 + // processed, none of the which are originally claimed. The number of 1.425 + // threads doing the tasks is initialized 1. 1.426 + SubTasksDone(uint n); 1.427 + 1.428 + // True iff the object is in a valid state. 1.429 + bool valid(); 1.430 + 1.431 + // Get/set the number of parallel threads doing the tasks to "t". Can only 1.432 + // be called before tasks start or after they are complete. 1.433 + uint n_threads() { return _n_threads; } 1.434 + void set_n_threads(uint t); 1.435 + 1.436 + // Returns "false" if the task "t" is unclaimed, and ensures that task is 1.437 + // claimed. The task "t" is required to be within the range of "this". 1.438 + bool is_task_claimed(uint t); 1.439 + 1.440 + // The calling thread asserts that it has attempted to claim all the 1.441 + // tasks that it will try to claim. Every thread in the parallel task 1.442 + // must execute this. (When the last thread does so, the task array is 1.443 + // cleared.) 1.444 + void all_tasks_completed(); 1.445 + 1.446 + // Destructor. 1.447 + ~SubTasksDone(); 1.448 +}; 1.449 + 1.450 +// As above, but for sequential tasks, i.e. instead of claiming 1.451 +// sub-tasks from a set (possibly an enumeration), claim sub-tasks 1.452 +// in sequential order. This is ideal for claiming dynamically 1.453 +// partitioned tasks (like striding in the parallel remembered 1.454 +// set scanning). Note that unlike the above class this is 1.455 +// a stack object - is there any reason for it not to be? 1.456 + 1.457 +class SequentialSubTasksDone : public StackObj { 1.458 +protected: 1.459 + uint _n_tasks; // Total number of tasks available. 1.460 + uint _n_claimed; // Number of tasks claimed. 1.461 + // _n_threads is used to determine when a sub task is done. 1.462 + // See comments on SubTasksDone::_n_threads 1.463 + uint _n_threads; // Total number of parallel threads. 1.464 + uint _n_completed; // Number of completed threads. 1.465 + 1.466 + void clear(); 1.467 + 1.468 +public: 1.469 + SequentialSubTasksDone() { 1.470 + clear(); 1.471 + } 1.472 + ~SequentialSubTasksDone() {} 1.473 + 1.474 + // True iff the object is in a valid state. 1.475 + bool valid(); 1.476 + 1.477 + // number of tasks 1.478 + uint n_tasks() const { return _n_tasks; } 1.479 + 1.480 + // Get/set the number of parallel threads doing the tasks to t. 1.481 + // Should be called before the task starts but it is safe 1.482 + // to call this once a task is running provided that all 1.483 + // threads agree on the number of threads. 1.484 + uint n_threads() { return _n_threads; } 1.485 + void set_n_threads(uint t) { _n_threads = t; } 1.486 + 1.487 + // Set the number of tasks to be claimed to t. As above, 1.488 + // should be called before the tasks start but it is safe 1.489 + // to call this once a task is running provided all threads 1.490 + // agree on the number of tasks. 1.491 + void set_n_tasks(uint t) { _n_tasks = t; } 1.492 + 1.493 + // Returns false if the next task in the sequence is unclaimed, 1.494 + // and ensures that it is claimed. Will set t to be the index 1.495 + // of the claimed task in the sequence. Will return true if 1.496 + // the task cannot be claimed and there are none left to claim. 1.497 + bool is_task_claimed(uint& t); 1.498 + 1.499 + // The calling thread asserts that it has attempted to claim 1.500 + // all the tasks it possibly can in the sequence. Every thread 1.501 + // claiming tasks must promise call this. Returns true if this 1.502 + // is the last thread to complete so that the thread can perform 1.503 + // cleanup if necessary. 1.504 + bool all_tasks_completed(); 1.505 +}; 1.506 + 1.507 +// Represents a set of free small integer ids. 1.508 +class FreeIdSet : public CHeapObj<mtInternal> { 1.509 + enum { 1.510 + end_of_list = -1, 1.511 + claimed = -2 1.512 + }; 1.513 + 1.514 + int _sz; 1.515 + Monitor* _mon; 1.516 + 1.517 + int* _ids; 1.518 + int _hd; 1.519 + int _waiters; 1.520 + int _claimed; 1.521 + 1.522 + static bool _safepoint; 1.523 + typedef FreeIdSet* FreeIdSetPtr; 1.524 + static const int NSets = 10; 1.525 + static FreeIdSetPtr _sets[NSets]; 1.526 + static bool _stat_init; 1.527 + int _index; 1.528 + 1.529 +public: 1.530 + FreeIdSet(int sz, Monitor* mon); 1.531 + ~FreeIdSet(); 1.532 + 1.533 + static void set_safepoint(bool b); 1.534 + 1.535 + // Attempt to claim the given id permanently. Returns "true" iff 1.536 + // successful. 1.537 + bool claim_perm_id(int i); 1.538 + 1.539 + // Returns an unclaimed parallel id (waiting for one to be released if 1.540 + // necessary). Returns "-1" if a GC wakes up a wait for an id. 1.541 + int claim_par_id(); 1.542 + 1.543 + void release_par_id(int id); 1.544 +}; 1.545 + 1.546 +#endif // SHARE_VM_UTILITIES_WORKGROUP_HPP