1 /* 2 * Copyright (c) 2002, 2020, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #ifndef SHARE_GC_SHARED_WORKGROUP_HPP 26 #define SHARE_GC_SHARED_WORKGROUP_HPP 27 28 #include "memory/allocation.hpp" 29 #include "runtime/globals.hpp" 30 #include "runtime/thread.hpp" 31 #include "gc/shared/gcId.hpp" 32 #include "logging/log.hpp" 33 #include "utilities/debug.hpp" 34 #include "utilities/globalDefinitions.hpp" 35 36 // Task class hierarchy: 37 // AbstractGangTask 38 // 39 // Gang/Group class hierarchy: 40 // AbstractWorkGang 41 // WorkGang 42 // YieldingFlexibleWorkGang (defined in another file) 43 // 44 // Worker class hierarchy: 45 // AbstractGangWorker (subclass of WorkerThread) 46 // GangWorker 47 // YieldingFlexibleGangWorker (defined in another file) 48 49 // Forward declarations of classes defined here 50 51 class AbstractGangWorker; 52 class Semaphore; 53 class ThreadClosure; 54 class WorkGang; 55 class GangTaskDispatcher; 56 57 // An abstract task to be worked on by a gang. 58 // You subclass this to supply your own work() method 59 class AbstractGangTask { 60 const char* _name; 61 const uint _gc_id; 62 63 public: 64 explicit AbstractGangTask(const char* name) : 65 _name(name), 66 _gc_id(GCId::current_or_undefined()) 67 {} 68 69 // The abstract work method. 70 // The argument tells you which member of the gang you are. 71 virtual void work(uint worker_id) = 0; 72 73 // Debugging accessor for the name. 74 const char* name() const { return _name; } 75 const uint gc_id() const { return _gc_id; } 76 }; 77 78 struct WorkData { 79 AbstractGangTask* _task; 80 uint _worker_id; 81 WorkData(AbstractGangTask* task, uint worker_id) : _task(task), _worker_id(worker_id) {} 82 }; 83 84 // The work gang is the collection of workers to execute tasks. 85 // The number of workers run for a task is "_active_workers" 86 // while "_total_workers" is the number of available of workers. 87 class AbstractWorkGang : public CHeapObj<mtInternal> { 88 protected: 89 // The array of worker threads for this gang. 90 AbstractGangWorker** _workers; 91 // The count of the number of workers in the gang. 92 uint _total_workers; 93 // The currently active workers in this gang. 94 uint _active_workers; 95 // The count of created workers in the gang. 96 uint _created_workers; 97 // Printing support. 98 const char* _name; 99 100 ~AbstractWorkGang() {} 101 102 private: 103 // Initialize only instance data. 104 const bool _are_GC_task_threads; 105 const bool _are_ConcurrentGC_threads; 106 107 void set_thread(uint worker_id, AbstractGangWorker* worker) { 108 _workers[worker_id] = worker; 109 } 110 111 public: 112 AbstractWorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads) : 113 _workers(NULL), 114 _total_workers(workers), 115 _active_workers(UseDynamicNumberOfGCThreads ? 1U : workers), 116 _created_workers(0), 117 _name(name), 118 _are_GC_task_threads(are_GC_task_threads), 119 _are_ConcurrentGC_threads(are_ConcurrentGC_threads) 120 { } 121 122 // Initialize workers in the gang. Return true if initialization succeeded. 123 void initialize_workers(); 124 125 bool are_GC_task_threads() const { return _are_GC_task_threads; } 126 bool are_ConcurrentGC_threads() const { return _are_ConcurrentGC_threads; } 127 128 uint total_workers() const { return _total_workers; } 129 130 uint created_workers() const { 131 return _created_workers; 132 } 133 134 virtual uint active_workers() const { 135 assert(_active_workers <= _total_workers, 136 "_active_workers: %u > _total_workers: %u", _active_workers, _total_workers); 137 return _active_workers; 138 } 139 140 uint update_active_workers(uint v) { 141 assert(v <= _total_workers, 142 "Trying to set more workers active than there are"); 143 _active_workers = MIN2(v, _total_workers); 144 add_workers(false /* exit_on_failure */); 145 assert(v != 0, "Trying to set active workers to 0"); 146 log_trace(gc, task)("%s: using %d out of %d workers", name(), _active_workers, _total_workers); 147 return _active_workers; 148 } 149 150 // Add GC workers as needed. 151 void add_workers(bool initializing); 152 153 // Add GC workers as needed to reach the specified number of workers. 154 void add_workers(uint active_workers, bool initializing); 155 156 // Return the Ith worker. 157 AbstractGangWorker* worker(uint i) const; 158 159 // Base name (without worker id #) of threads. 160 const char* group_name() { return name(); } 161 162 void threads_do(ThreadClosure* tc) const; 163 164 // Create a GC worker and install it into the work gang. 165 virtual AbstractGangWorker* install_worker(uint which); 166 167 // Debugging. 168 const char* name() const { return _name; } 169 170 protected: 171 virtual AbstractGangWorker* allocate_worker(uint which) = 0; 172 }; 173 174 // An class representing a gang of workers. 175 class WorkGang: public AbstractWorkGang { 176 // To get access to the GangTaskDispatcher instance. 177 friend class GangWorker; 178 179 GangTaskDispatcher* const _dispatcher; 180 GangTaskDispatcher* dispatcher() const { 181 return _dispatcher; 182 } 183 184 public: 185 WorkGang(const char* name, 186 uint workers, 187 bool are_GC_task_threads, 188 bool are_ConcurrentGC_threads); 189 190 ~WorkGang(); 191 192 // Run a task using the current active number of workers, returns when the task is done. 193 virtual void run_task(AbstractGangTask* task); 194 // Run a task with the given number of workers, returns 195 // when the task is done. The number of workers must be at most the number of 196 // active workers. Additional workers may be created if an insufficient 197 // number currently exists. If the add_foreground_work flag is true, the current thread 198 // is used to run the task too. 199 void run_task(AbstractGangTask* task, uint num_workers, bool add_foreground_work = false); 200 201 protected: 202 virtual AbstractGangWorker* allocate_worker(uint which); 203 }; 204 205 // Temporarily try to set the number of active workers. 206 // It's not guaranteed that it succeeds, and users need to 207 // query the number of active workers. 208 class WithUpdatedActiveWorkers : public StackObj { 209 private: 210 AbstractWorkGang* const _gang; 211 const uint _old_active_workers; 212 213 public: 214 WithUpdatedActiveWorkers(AbstractWorkGang* gang, uint requested_num_workers) : 215 _gang(gang), 216 _old_active_workers(gang->active_workers()) { 217 uint capped_num_workers = MIN2(requested_num_workers, gang->total_workers()); 218 gang->update_active_workers(capped_num_workers); 219 } 220 221 ~WithUpdatedActiveWorkers() { 222 _gang->update_active_workers(_old_active_workers); 223 } 224 }; 225 226 // Several instances of this class run in parallel as workers for a gang. 227 class AbstractGangWorker: public WorkerThread { 228 public: 229 AbstractGangWorker(AbstractWorkGang* gang, uint id); 230 231 // The only real method: run a task for the gang. 232 virtual void run(); 233 // Predicate for Thread 234 virtual bool is_GC_task_thread() const; 235 virtual bool is_ConcurrentGC_thread() const; 236 // Printing 237 void print_on(outputStream* st) const; 238 virtual void print() const; 239 240 protected: 241 AbstractWorkGang* _gang; 242 243 virtual void initialize(); 244 virtual void loop() = 0; 245 246 AbstractWorkGang* gang() const { return _gang; } 247 }; 248 249 class GangWorker: public AbstractGangWorker { 250 public: 251 GangWorker(WorkGang* gang, uint id) : AbstractGangWorker(gang, id) {} 252 253 protected: 254 virtual void loop(); 255 256 private: 257 WorkData wait_for_task(); 258 void run_task(WorkData work); 259 void signal_task_done(); 260 261 WorkGang* gang() const { return (WorkGang*)_gang; } 262 }; 263 264 // A class that acts as a synchronisation barrier. Workers enter 265 // the barrier and must wait until all other workers have entered 266 // before any of them may leave. 267 268 class WorkGangBarrierSync : public StackObj { 269 protected: 270 Monitor _monitor; 271 uint _n_workers; 272 uint _n_completed; 273 bool _should_reset; 274 bool _aborted; 275 276 Monitor* monitor() { return &_monitor; } 277 uint n_workers() { return _n_workers; } 278 uint n_completed() { return _n_completed; } 279 bool should_reset() { return _should_reset; } 280 bool aborted() { return _aborted; } 281 282 void zero_completed() { _n_completed = 0; } 283 void inc_completed() { _n_completed++; } 284 void set_aborted() { _aborted = true; } 285 void set_should_reset(bool v) { _should_reset = v; } 286 287 public: 288 WorkGangBarrierSync(); 289 WorkGangBarrierSync(uint n_workers, const char* name); 290 291 // Set the number of workers that will use the barrier. 292 // Must be called before any of the workers start running. 293 void set_n_workers(uint n_workers); 294 295 // Enter the barrier. A worker that enters the barrier will 296 // not be allowed to leave until all other threads have 297 // also entered the barrier or the barrier is aborted. 298 // Returns false if the barrier was aborted. 299 bool enter(); 300 301 // Aborts the barrier and wakes up any threads waiting for 302 // the barrier to complete. The barrier will remain in the 303 // aborted state until the next call to set_n_workers(). 304 void abort(); 305 }; 306 307 // A class to manage claiming of subtasks within a group of tasks. The 308 // subtasks will be identified by integer indices, usually elements of an 309 // enumeration type. 310 311 class SubTasksDone: public CHeapObj<mtInternal> { 312 volatile uint* _tasks; 313 uint _n_tasks; 314 volatile uint _threads_completed; 315 #ifdef ASSERT 316 volatile uint _claimed; 317 #endif 318 319 // Set all tasks to unclaimed. 320 void clear(); 321 322 NONCOPYABLE(SubTasksDone); 323 324 public: 325 // Initializes "this" to a state in which there are "n" tasks to be 326 // processed, none of the which are originally claimed. The number of 327 // threads doing the tasks is initialized 1. 328 SubTasksDone(uint n); 329 330 // True iff the object is in a valid state. 331 bool valid(); 332 333 // Attempt to claim the task "t", returning true if successful, 334 // false if it has already been claimed. The task "t" is required 335 // to be within the range of "this". 336 bool try_claim_task(uint t); 337 338 // The calling thread asserts that it has attempted to claim all the 339 // tasks that it will try to claim. Every thread in the parallel task 340 // must execute this. (When the last thread does so, the task array is 341 // cleared.) 342 // 343 // n_threads - Number of threads executing the sub-tasks. 344 void all_tasks_completed(uint n_threads); 345 346 // Destructor. 347 ~SubTasksDone(); 348 }; 349 350 // As above, but for sequential tasks, i.e. instead of claiming 351 // sub-tasks from a set (possibly an enumeration), claim sub-tasks 352 // in sequential order. This is ideal for claiming dynamically 353 // partitioned tasks (like striding in the parallel remembered 354 // set scanning). Note that unlike the above class this is 355 // a stack object - is there any reason for it not to be? 356 357 class SequentialSubTasksDone : public StackObj { 358 protected: 359 uint _n_tasks; // Total number of tasks available. 360 volatile uint _n_claimed; // Number of tasks claimed. 361 // _n_threads is used to determine when a sub task is done. 362 // See comments on SubTasksDone::_n_threads 363 uint _n_threads; // Total number of parallel threads. 364 volatile uint _n_completed; // Number of completed threads. 365 366 void clear(); 367 368 public: 369 SequentialSubTasksDone() { 370 clear(); 371 } 372 ~SequentialSubTasksDone() {} 373 374 // True iff the object is in a valid state. 375 bool valid(); 376 377 // number of tasks 378 uint n_tasks() const { return _n_tasks; } 379 380 // Get/set the number of parallel threads doing the tasks to t. 381 // Should be called before the task starts but it is safe 382 // to call this once a task is running provided that all 383 // threads agree on the number of threads. 384 uint n_threads() { return _n_threads; } 385 void set_n_threads(uint t) { _n_threads = t; } 386 387 // Set the number of tasks to be claimed to t. As above, 388 // should be called before the tasks start but it is safe 389 // to call this once a task is running provided all threads 390 // agree on the number of tasks. 391 void set_n_tasks(uint t) { _n_tasks = t; } 392 393 // Attempt to claim the next unclaimed task in the sequence, 394 // returning true if successful, with t set to the index of the 395 // claimed task. Returns false if there are no more unclaimed tasks 396 // in the sequence. 397 bool try_claim_task(uint& t); 398 399 // The calling thread asserts that it has attempted to claim 400 // all the tasks it possibly can in the sequence. Every thread 401 // claiming tasks must promise call this. Returns true if this 402 // is the last thread to complete so that the thread can perform 403 // cleanup if necessary. 404 bool all_tasks_completed(); 405 }; 406 407 #endif // SHARE_GC_SHARED_WORKGROUP_HPP