1 /*
2  * Copyright (c) 2002, 2021, 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 "metaprogramming/enableIf.hpp"
30 #include "metaprogramming/logical.hpp"
31 #include "runtime/globals.hpp"
32 #include "runtime/nonJavaThread.hpp"
33 #include "runtime/thread.hpp"
34 #include "gc/shared/gcId.hpp"
35 #include "logging/log.hpp"
36 #include "utilities/debug.hpp"
37 #include "utilities/globalDefinitions.hpp"
38 
39 // Task class hierarchy:
40 //   AbstractGangTask
41 //
42 // Gang/Group class hierarchy:
43 //   WorkGang
44 //
45 // Worker class hierarchy:
46 //   GangWorker (subclass of WorkerThread)
47 
48 // Forward declarations of classes defined here
49 
50 class GangWorker;
51 class Semaphore;
52 class ThreadClosure;
53 class GangTaskDispatcher;
54 
55 // An abstract task to be worked on by a gang.
56 // You subclass this to supply your own work() method
57 class AbstractGangTask : public CHeapObj<mtInternal> {
58   const char* _name;
59   const uint _gc_id;
60 
61  public:
AbstractGangTask(const char * name)62   explicit AbstractGangTask(const char* name) :
63     _name(name),
64     _gc_id(GCId::current_or_undefined())
65   {}
66 
67   // The abstract work method.
68   // The argument tells you which member of the gang you are.
69   virtual void work(uint worker_id) = 0;
70 
71   // Debugging accessor for the name.
name() const72   const char* name() const { return _name; }
gc_id() const73   const uint gc_id() const { return _gc_id; }
74 };
75 
76 struct WorkData {
77   AbstractGangTask* _task;
78   uint              _worker_id;
WorkDataWorkData79   WorkData(AbstractGangTask* task, uint worker_id) : _task(task), _worker_id(worker_id) {}
80 };
81 
82 // The work gang is the collection of workers to execute tasks.
83 // The number of workers run for a task is "_active_workers"
84 // while "_total_workers" is the number of available workers.
85 class WorkGang : public CHeapObj<mtInternal> {
86   // The array of worker threads for this gang.
87   GangWorker** _workers;
88   // The count of the number of workers in the gang.
89   uint _total_workers;
90   // The currently active workers in this gang.
91   uint _active_workers;
92   // The count of created workers in the gang.
93   uint _created_workers;
94   // Printing support.
95   const char* _name;
96 
97   // Initialize only instance data.
98   const bool _are_GC_task_threads;
99   const bool _are_ConcurrentGC_threads;
100 
101   // To get access to the GangTaskDispatcher instance.
102   friend class GangWorker;
103   GangTaskDispatcher* const _dispatcher;
104 
dispatcher() const105   GangTaskDispatcher* dispatcher() const { return _dispatcher; }
106 
set_thread(uint worker_id,GangWorker * worker)107   void set_thread(uint worker_id, GangWorker* worker) {
108     _workers[worker_id] = worker;
109   }
110 
111   // Add GC workers when _created_workers < _active_workers; otherwise, no-op.
112   // If there's no memory/thread allocation failure, _created_worker is
113   // adjusted to match _active_workers (_created_worker == _active_workers).
114   void add_workers(bool initializing);
115 
116   GangWorker* allocate_worker(uint which);
117 
118  public:
119   WorkGang(const char* name, uint workers, bool are_GC_task_threads, bool are_ConcurrentGC_threads);
120 
121   ~WorkGang();
122 
123   // Initialize workers in the gang.  Return true if initialization succeeded.
124   void initialize_workers();
125 
are_GC_task_threads() const126   bool are_GC_task_threads()      const { return _are_GC_task_threads; }
are_ConcurrentGC_threads() const127   bool are_ConcurrentGC_threads() const { return _are_ConcurrentGC_threads; }
128 
total_workers() const129   uint total_workers() const { return _total_workers; }
130 
created_workers() const131   uint created_workers() const {
132     return _created_workers;
133   }
134 
active_workers() const135   uint active_workers() const {
136     assert(_active_workers != 0, "zero active workers");
137     assert(_active_workers <= _total_workers,
138            "_active_workers: %u > _total_workers: %u", _active_workers, _total_workers);
139     return _active_workers;
140   }
141 
update_active_workers(uint v)142   uint update_active_workers(uint v) {
143     assert(v <= _total_workers,
144            "Trying to set more workers active than there are");
145     assert(v != 0, "Trying to set active workers to 0");
146     _active_workers = v;
147     add_workers(false /* initializing */);
148     log_trace(gc, task)("%s: using %d out of %d workers", name(), _active_workers, _total_workers);
149     return _active_workers;
150   }
151 
152   // Return the Ith worker.
153   GangWorker* worker(uint i) const;
154 
155   // Base name (without worker id #) of threads.
group_name()156   const char* group_name() { return name(); }
157 
158   void threads_do(ThreadClosure* tc) const;
159 
160   // Create a GC worker and install it into the work gang.
161   virtual GangWorker* install_worker(uint which);
162 
163   // Debugging.
name() const164   const char* name() const { return _name; }
165 
166   // Run a task using the current active number of workers, returns when the task is done.
167   void run_task(AbstractGangTask* task);
168 
169   // Run a task with the given number of workers, returns
170   // when the task is done. The number of workers must be at most the number of
171   // active workers.  Additional workers may be created if an insufficient
172   // number currently exists. If the add_foreground_work flag is true, the current thread
173   // is used to run the task too.
174   void run_task(AbstractGangTask* task, uint num_workers, bool add_foreground_work = false);
175 };
176 
177 // Temporarily try to set the number of active workers.
178 // It's not guaranteed that it succeeds, and users need to
179 // query the number of active workers.
180 class WithUpdatedActiveWorkers : public StackObj {
181 private:
182   WorkGang* const _gang;
183   const uint              _old_active_workers;
184 
185 public:
WithUpdatedActiveWorkers(WorkGang * gang,uint requested_num_workers)186   WithUpdatedActiveWorkers(WorkGang* gang, uint requested_num_workers) :
187       _gang(gang),
188       _old_active_workers(gang->active_workers()) {
189     uint capped_num_workers = MIN2(requested_num_workers, gang->total_workers());
190     gang->update_active_workers(capped_num_workers);
191   }
192 
~WithUpdatedActiveWorkers()193   ~WithUpdatedActiveWorkers() {
194     _gang->update_active_workers(_old_active_workers);
195   }
196 };
197 
198 // Several instances of this class run in parallel as workers for a gang.
199 class GangWorker: public WorkerThread {
200 private:
201   WorkGang* _gang;
202 
203   void initialize();
204   void loop();
205 
gang() const206   WorkGang* gang() const { return _gang; }
207 
208   WorkData wait_for_task();
209   void run_task(WorkData work);
210   void signal_task_done();
211 
212 protected:
213   // The only real method: run a task for the gang.
214   void run() override;
215 
216 public:
217   GangWorker(WorkGang* gang, uint id);
218 
219   // Predicate for Thread
is_GC_task_thread() const220   bool is_GC_task_thread() const override { return gang()->are_GC_task_threads(); }
is_ConcurrentGC_thread() const221   bool is_ConcurrentGC_thread() const override { return gang()->are_ConcurrentGC_threads(); }
222 };
223 
224 // A class that acts as a synchronisation barrier. Workers enter
225 // the barrier and must wait until all other workers have entered
226 // before any of them may leave.
227 
228 class WorkGangBarrierSync : public StackObj {
229 protected:
230   Monitor _monitor;
231   uint    _n_workers;
232   uint    _n_completed;
233   bool    _should_reset;
234   bool    _aborted;
235 
monitor()236   Monitor* monitor()        { return &_monitor; }
n_workers()237   uint     n_workers()      { return _n_workers; }
n_completed()238   uint     n_completed()    { return _n_completed; }
should_reset()239   bool     should_reset()   { return _should_reset; }
aborted()240   bool     aborted()        { return _aborted; }
241 
zero_completed()242   void     zero_completed() { _n_completed = 0; }
inc_completed()243   void     inc_completed()  { _n_completed++; }
set_aborted()244   void     set_aborted()    { _aborted = true; }
set_should_reset(bool v)245   void     set_should_reset(bool v) { _should_reset = v; }
246 
247 public:
248   WorkGangBarrierSync();
249   WorkGangBarrierSync(uint n_workers, const char* name);
250 
251   // Set the number of workers that will use the barrier.
252   // Must be called before any of the workers start running.
253   void set_n_workers(uint n_workers);
254 
255   // Enter the barrier. A worker that enters the barrier will
256   // not be allowed to leave until all other threads have
257   // also entered the barrier or the barrier is aborted.
258   // Returns false if the barrier was aborted.
259   bool enter();
260 
261   // Aborts the barrier and wakes up any threads waiting for
262   // the barrier to complete. The barrier will remain in the
263   // aborted state until the next call to set_n_workers().
264   void abort();
265 };
266 
267 // A class to manage claiming of subtasks within a group of tasks.  The
268 // subtasks will be identified by integer indices, usually elements of an
269 // enumeration type.
270 
271 class SubTasksDone: public CHeapObj<mtInternal> {
272   volatile bool* _tasks;
273   uint _n_tasks;
274 
275   // make sure verification logic is run exactly once to avoid duplicate assertion failures
276   DEBUG_ONLY(volatile bool _verification_done = false;)
277   void all_tasks_claimed_impl(uint skipped[], size_t skipped_size) NOT_DEBUG_RETURN;
278 
279   NONCOPYABLE(SubTasksDone);
280 
281 public:
282   // Initializes "this" to a state in which there are "n" tasks to be
283   // processed, none of the which are originally claimed.
284   SubTasksDone(uint n);
285 
286   // Attempt to claim the task "t", returning true if successful,
287   // false if it has already been claimed.  The task "t" is required
288   // to be within the range of "this".
289   bool try_claim_task(uint t);
290 
291   // The calling thread asserts that it has attempted to claim all the tasks
292   // that it will try to claim.  Tasks that are meant to be skipped must be
293   // explicitly passed as extra arguments. Every thread in the parallel task
294   // must execute this.
295   template<typename T0, typename... Ts,
296           ENABLE_IF(Conjunction<std::is_same<T0, Ts>...>::value)>
all_tasks_claimed(T0 first_skipped,Ts...more_skipped)297   void all_tasks_claimed(T0 first_skipped, Ts... more_skipped) {
298     static_assert(std::is_convertible<T0, uint>::value, "not convertible");
299     uint skipped[] = { static_cast<uint>(first_skipped), static_cast<uint>(more_skipped)... };
300     all_tasks_claimed_impl(skipped, ARRAY_SIZE(skipped));
301   }
302   // if there are no skipped tasks.
all_tasks_claimed()303   void all_tasks_claimed() {
304     all_tasks_claimed_impl(nullptr, 0);
305   }
306 
307   // Destructor.
308   ~SubTasksDone();
309 };
310 
311 // As above, but for sequential tasks, i.e. instead of claiming
312 // sub-tasks from a set (possibly an enumeration), claim sub-tasks
313 // in sequential order. This is ideal for claiming dynamically
314 // partitioned tasks (like striding in the parallel remembered
315 // set scanning).
316 
317 class SequentialSubTasksDone : public CHeapObj<mtInternal> {
318 
319   uint _num_tasks;     // Total number of tasks available.
320   volatile uint _num_claimed;   // Number of tasks claimed.
321 
322   NONCOPYABLE(SequentialSubTasksDone);
323 
324 public:
SequentialSubTasksDone(uint num_tasks)325   SequentialSubTasksDone(uint num_tasks) : _num_tasks(num_tasks), _num_claimed(0) { }
~SequentialSubTasksDone()326   ~SequentialSubTasksDone() {
327     // Claiming may try to claim more tasks than there are.
328     assert(_num_claimed >= _num_tasks, "Claimed %u tasks of %u", _num_claimed, _num_tasks);
329   }
330 
331   // Attempt to claim the next unclaimed task in the sequence,
332   // returning true if successful, with t set to the index of the
333   // claimed task. Returns false if there are no more unclaimed tasks
334   // in the sequence. In this case t is undefined.
335   bool try_claim_task(uint& t);
336 };
337 
338 #endif // SHARE_GC_SHARED_WORKGROUP_HPP
339