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:
AbstractGangTask(const char * name)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.
name() const74   const char* name() const { return _name; }
gc_id() const75   const uint gc_id() const { return _gc_id; }
76 };
77 
78 struct WorkData {
79   AbstractGangTask* _task;
80   uint              _worker_id;
WorkDataWorkData81   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 
~AbstractWorkGang()100   ~AbstractWorkGang() {}
101 
102  private:
103   // Initialize only instance data.
104   const bool _are_GC_task_threads;
105   const bool _are_ConcurrentGC_threads;
106 
set_thread(uint worker_id,AbstractGangWorker * worker)107   void set_thread(uint worker_id, AbstractGangWorker* worker) {
108     _workers[worker_id] = worker;
109   }
110 
111  public:
AbstractWorkGang(const char * name,uint workers,bool are_GC_task_threads,bool are_ConcurrentGC_threads)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 
are_GC_task_threads() const125   bool are_GC_task_threads()      const { return _are_GC_task_threads; }
are_ConcurrentGC_threads() const126   bool are_ConcurrentGC_threads() const { return _are_ConcurrentGC_threads; }
127 
total_workers() const128   uint total_workers() const { return _total_workers; }
129 
created_workers() const130   uint created_workers() const {
131     return _created_workers;
132   }
133 
active_workers() const134   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 
update_active_workers(uint v)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.
group_name()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.
name() const168   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;
dispatcher() const180   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:
WithUpdatedActiveWorkers(AbstractWorkGang * gang,uint requested_num_workers)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 
~WithUpdatedActiveWorkers()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 
gang() const246   AbstractWorkGang* gang() const { return _gang; }
247 };
248 
249 class GangWorker: public AbstractGangWorker {
250 public:
GangWorker(WorkGang * gang,uint id)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 
gang() const261   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 
monitor()276   Monitor* monitor()        { return &_monitor; }
n_workers()277   uint     n_workers()      { return _n_workers; }
n_completed()278   uint     n_completed()    { return _n_completed; }
should_reset()279   bool     should_reset()   { return _should_reset; }
aborted()280   bool     aborted()        { return _aborted; }
281 
zero_completed()282   void     zero_completed() { _n_completed = 0; }
inc_completed()283   void     inc_completed()  { _n_completed++; }
set_aborted()284   void     set_aborted()    { _aborted = true; }
set_should_reset(bool v)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:
SequentialSubTasksDone()369   SequentialSubTasksDone() {
370     clear();
371   }
~SequentialSubTasksDone()372   ~SequentialSubTasksDone() {}
373 
374   // True iff the object is in a valid state.
375   bool valid();
376 
377   // number of tasks
n_tasks() const378   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.
n_threads()384   uint n_threads() { return _n_threads; }
set_n_threads(uint t)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.
set_n_tasks(uint t)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
408