1/*
2 * Copyright (c) 2005, 2019, 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#include "precompiled.hpp"
26#include "gc/cms/yieldingWorkgroup.hpp"
27#include "gc/shared/gcId.hpp"
28#include "utilities/macros.hpp"
29
30YieldingFlexibleGangWorker::YieldingFlexibleGangWorker(YieldingFlexibleWorkGang* gang, int id)
31 : AbstractGangWorker(gang, id) {}
32
33YieldingFlexibleWorkGang::YieldingFlexibleWorkGang(
34 const char* name, uint workers, bool are_GC_task_threads) :
35 AbstractWorkGang(name, workers, are_GC_task_threads, false),
36 _yielded_workers(0),
37 _started_workers(0),
38 _finished_workers(0),
39 _sequence_number(0),
40 _task(NULL) {
41
42 // Other initialization.
43 _monitor = new Monitor(/* priority */ Mutex::leaf,
44 /* name */ "WorkGroup monitor",
45 /* allow_vm_block */ are_GC_task_threads,
46 Monitor::_safepoint_check_never);
47
48 assert(monitor() != NULL, "Failed to allocate monitor");
49}
50
51AbstractGangWorker* YieldingFlexibleWorkGang::allocate_worker(uint which) {
52 return new YieldingFlexibleGangWorker(this, which);
53}
54
55void YieldingFlexibleWorkGang::internal_worker_poll(YieldingWorkData* data) const {
56 assert(data != NULL, "worker data is null");
57 data->set_task(task());
58 data->set_sequence_number(sequence_number());
59}
60
61void YieldingFlexibleWorkGang::internal_note_start() {
62 assert(monitor()->owned_by_self(), "note_finish is an internal method");
63 _started_workers += 1;
64}
65
66void YieldingFlexibleWorkGang::internal_note_finish() {
67 assert(monitor()->owned_by_self(), "note_finish is an internal method");
68 _finished_workers += 1;
69}
70
71// Run a task; returns when the task is done, or the workers yield,
72// or the task is aborted.
73// A task that has been yielded can be continued via this interface
74// by using the same task repeatedly as the argument to the call.
75// It is expected that the YieldingFlexibleGangTask carries the appropriate
76// continuation information used by workers to continue the task
77// from its last yield point. Thus, a completed task will return
78// immediately with no actual work having been done by the workers.
79/////////////////////
80// Implementatiuon notes: remove before checking XXX
81/*
82Each gang is working on a task at a certain time.
83Some subset of workers may have yielded and some may
84have finished their quota of work. Until this task has
85been completed, the workers are bound to that task.
86Once the task has been completed, the gang unbounds
87itself from the task.
88
89The yielding work gang thus exports two invokation
90interfaces: run_task() and continue_task(). The
91first is used to initiate a new task and bind it
92to the workers; the second is used to continue an
93already bound task that has yielded. Upon completion
94the binding is released and a new binding may be
95created.
96
97The shape of a yielding work gang is as follows:
98
99Overseer invokes run_task(*task).
100 Lock gang monitor
101 Check that there is no existing binding for the gang
102 If so, abort with an error
103 Else, create a new binding of this gang to the given task
104 Set number of active workers (as asked)
105 Notify workers that work is ready to be done
106 [the requisite # workers would then start up
107 and do the task]
108 Wait on the monitor until either
109 all work is completed or the task has yielded
110 -- this is normally done through
111 yielded + completed == active
112 [completed workers are rest to idle state by overseer?]
113 return appropriate status to caller
114
115Overseer invokes continue_task(*task),
116 Lock gang monitor
117 Check that task is the same as current binding
118 If not, abort with an error
119 Else, set the number of active workers as requested?
120 Notify workers that they can continue from yield points
121 New workers can also start up as required
122 while satisfying the constraint that
123 active + yielded does not exceed required number
124 Wait (as above).
125
126NOTE: In the above, for simplicity in a first iteration
127 our gangs will be of fixed population and will not
128 therefore be flexible work gangs, just yielding work
129 gangs. Once this works well, we will in a second
130 iteration.refinement introduce flexibility into
131 the work gang.
132
133NOTE: we can always create a new gang per each iteration
134 in order to get the flexibility, but we will for now
135 desist that simplified route.
136
137 */
138/////////////////////
139void YieldingFlexibleWorkGang::start_task(YieldingFlexibleGangTask* new_task) {
140 MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
141 assert(task() == NULL, "Gang currently tied to a task");
142 assert(new_task != NULL, "Null task");
143 // Bind task to gang
144 _task = new_task;
145 new_task->set_gang(this); // Establish 2-way binding to support yielding
146 _sequence_number++;
147
148 uint requested_size = new_task->requested_size();
149 if (requested_size != 0) {
150 _active_workers = MIN2(requested_size, total_workers());
151 } else {
152 _active_workers = active_workers();
153 }
154 new_task->set_actual_size(_active_workers);
155 new_task->set_for_termination(_active_workers);
156
157 assert(_started_workers == 0, "Tabula rasa non");
158 assert(_finished_workers == 0, "Tabula rasa non");
159 assert(_yielded_workers == 0, "Tabula rasa non");
160 yielding_task()->set_status(ACTIVE);
161
162 // Wake up all the workers, the first few will get to work,
163 // and the rest will go back to sleep
164 monitor()->notify_all();
165 wait_for_gang();
166}
167
168void YieldingFlexibleWorkGang::wait_for_gang() {
169
170 assert(monitor()->owned_by_self(), "Data race");
171 // Wait for task to complete or yield
172 for (Status status = yielding_task()->status();
173 status != COMPLETED && status != YIELDED && status != ABORTED;
174 status = yielding_task()->status()) {
175 assert(started_workers() <= active_workers(), "invariant");
176 assert(finished_workers() <= active_workers(), "invariant");
177 assert(yielded_workers() <= active_workers(), "invariant");
178 monitor()->wait_without_safepoint_check();
179 }
180 switch (yielding_task()->status()) {
181 case COMPLETED:
182 case ABORTED: {
183 assert(finished_workers() == active_workers(), "Inconsistent status");
184 assert(yielded_workers() == 0, "Invariant");
185 reset(); // for next task; gang<->task binding released
186 break;
187 }
188 case YIELDED: {
189 assert(yielded_workers() > 0, "Invariant");
190 assert(yielded_workers() + finished_workers() == active_workers(),
191 "Inconsistent counts");
192 break;
193 }
194 case ACTIVE:
195 case INACTIVE:
196 case COMPLETING:
197 case YIELDING:
198 case ABORTING:
199 default:
200 ShouldNotReachHere();
201 }
202}
203
204void YieldingFlexibleWorkGang::continue_task(
205 YieldingFlexibleGangTask* gang_task) {
206
207 MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
208 assert(task() != NULL && task() == gang_task, "Incorrect usage");
209 assert(_started_workers == _active_workers, "Precondition");
210 assert(_yielded_workers > 0 && yielding_task()->status() == YIELDED,
211 "Else why are we calling continue_task()");
212 // Restart the yielded gang workers
213 yielding_task()->set_status(ACTIVE);
214 monitor()->notify_all();
215 wait_for_gang();
216}
217
218void YieldingFlexibleWorkGang::reset() {
219 _started_workers = 0;
220 _finished_workers = 0;
221 yielding_task()->set_gang(NULL);
222 _task = NULL; // unbind gang from task
223}
224
225void YieldingFlexibleWorkGang::yield() {
226 assert(task() != NULL, "Inconsistency; should have task binding");
227 MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
228 assert(yielded_workers() < active_workers(), "Consistency check");
229 if (yielding_task()->status() == ABORTING) {
230 // Do not yield; we need to abort as soon as possible
231 // XXX NOTE: This can cause a performance pathology in the
232 // current implementation in Mustang, as of today, and
233 // pre-Mustang in that as soon as an overflow occurs,
234 // yields will not be honoured. The right way to proceed
235 // of course is to fix bug # TBF, so that abort's cause
236 // us to return at each potential yield point.
237 return;
238 }
239 if (++_yielded_workers + finished_workers() == active_workers()) {
240 yielding_task()->set_status(YIELDED);
241 monitor()->notify_all();
242 } else {
243 yielding_task()->set_status(YIELDING);
244 }
245
246 while (true) {
247 switch (yielding_task()->status()) {
248 case YIELDING:
249 case YIELDED: {
250 monitor()->wait_without_safepoint_check();
251 break; // from switch
252 }
253 case ACTIVE:
254 case ABORTING:
255 case COMPLETING: {
256 assert(_yielded_workers > 0, "Else why am i here?");
257 _yielded_workers--;
258 return;
259 }
260 case INACTIVE:
261 case ABORTED:
262 case COMPLETED:
263 default: {
264 ShouldNotReachHere();
265 }
266 }
267 }
268 // Only return is from inside switch statement above
269 ShouldNotReachHere();
270}
271
272void YieldingFlexibleWorkGang::abort() {
273 assert(task() != NULL, "Inconsistency; should have task binding");
274 MutexLocker ml(monitor(), Mutex::_no_safepoint_check_flag);
275 assert(yielded_workers() < active_workers(), "Consistency check");
276 #ifndef PRODUCT
277 switch (yielding_task()->status()) {
278 // allowed states
279 case ACTIVE:
280 case ABORTING:
281 case COMPLETING:
282 case YIELDING:
283 break;
284 // not allowed states
285 case INACTIVE:
286 case ABORTED:
287 case COMPLETED:
288 case YIELDED:
289 default:
290 ShouldNotReachHere();
291 }
292 #endif // !PRODUCT
293 Status prev_status = yielding_task()->status();
294 yielding_task()->set_status(ABORTING);
295 if (prev_status == YIELDING) {
296 assert(yielded_workers() > 0, "Inconsistency");
297 // At least one thread has yielded, wake it up
298 // so it can go back to waiting stations ASAP.
299 monitor()->notify_all();
300 }
301}
302
303///////////////////////////////
304// YieldingFlexibleGangTask
305///////////////////////////////
306void YieldingFlexibleGangTask::yield() {
307 assert(gang() != NULL, "No gang to signal");
308 gang()->yield();
309}
310
311void YieldingFlexibleGangTask::abort() {
312 assert(gang() != NULL, "No gang to signal");
313 gang()->abort();
314}
315
316///////////////////////////////
317// YieldingFlexibleGangWorker
318///////////////////////////////
319void YieldingFlexibleGangWorker::loop() {
320 int previous_sequence_number = 0;
321 Monitor* gang_monitor = yf_gang()->monitor();
322 MutexLocker ml(gang_monitor, Mutex::_no_safepoint_check_flag);
323 YieldingWorkData data;
324 int id;
325 while (true) {
326 // Check if there is work to do.
327 yf_gang()->internal_worker_poll(&data);
328 if (data.task() != NULL && data.sequence_number() != previous_sequence_number) {
329 // There is work to be done.
330 // First check if we need to become active or if there
331 // are already the requisite number of workers
332 if (yf_gang()->started_workers() == yf_gang()->active_workers()) {
333 // There are already enough workers, we do not need to
334 // to run; fall through and wait on monitor.
335 } else {
336 // We need to pitch in and do the work.
337 assert(yf_gang()->started_workers() < yf_gang()->active_workers(),
338 "Unexpected state");
339 id = yf_gang()->started_workers();
340 yf_gang()->internal_note_start();
341 // Now, release the gang mutex and do the work.
342 {
343 MutexUnlocker mul(gang_monitor, Mutex::_no_safepoint_check_flag);
344 GCIdMark gc_id_mark(data.task()->gc_id());
345 data.task()->work(id); // This might include yielding
346 }
347 // Reacquire monitor and note completion of this worker
348 yf_gang()->internal_note_finish();
349 // Update status of task based on whether all workers have
350 // finished or some have yielded
351 assert(data.task() == yf_gang()->task(), "Confused task binding");
352 if (yf_gang()->finished_workers() == yf_gang()->active_workers()) {
353 switch (data.yf_task()->status()) {
354 case ABORTING: {
355 data.yf_task()->set_status(ABORTED);
356 break;
357 }
358 case ACTIVE:
359 case COMPLETING: {
360 data.yf_task()->set_status(COMPLETED);
361 break;
362 }
363 default:
364 ShouldNotReachHere();
365 }
366 gang_monitor->notify_all(); // Notify overseer
367 } else { // at least one worker is still working or yielded
368 assert(yf_gang()->finished_workers() < yf_gang()->active_workers(),
369 "Counts inconsistent");
370 switch (data.yf_task()->status()) {
371 case ACTIVE: {
372 // first, but not only thread to complete
373 data.yf_task()->set_status(COMPLETING);
374 break;
375 }
376 case YIELDING: {
377 if (yf_gang()->finished_workers() + yf_gang()->yielded_workers()
378 == yf_gang()->active_workers()) {
379 data.yf_task()->set_status(YIELDED);
380 gang_monitor->notify_all(); // notify overseer
381 }
382 break;
383 }
384 case ABORTING:
385 case COMPLETING: {
386 break; // nothing to do
387 }
388 default: // everything else: INACTIVE, YIELDED, ABORTED, COMPLETED
389 ShouldNotReachHere();
390 }
391 }
392 }
393 }
394 // Remember the sequence number
395 previous_sequence_number = data.sequence_number();
396 // Wait for more work
397 gang_monitor->wait_without_safepoint_check();
398 }
399}
400