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 "utilities/macros.hpp" 28 29 // Forward declaration of classes declared here. 30 31 class GangWorker; 32 class WorkData; 33 34 YieldingFlexibleWorkGang::YieldingFlexibleWorkGang( 35 const char* name, uint workers, bool are_GC_task_threads) : 36 FlexibleWorkGang(name, workers, are_GC_task_threads, false), 37 _yielded_workers(0) {} 38 39 GangWorker* YieldingFlexibleWorkGang::allocate_worker(uint which) { 40 YieldingFlexibleGangWorker* new_member = 41 new YieldingFlexibleGangWorker(this, which); 42 return (YieldingFlexibleGangWorker*) new_member; 43 } 44 45 // Run a task; returns when the task is done, or the workers yield, 46 // or the task is aborted. 47 // A task that has been yielded can be continued via this interface 48 // by using the same task repeatedly as the argument to the call. 49 // It is expected that the YieldingFlexibleGangTask carries the appropriate 50 // continuation information used by workers to continue the task 51 // from its last yield point. Thus, a completed task will return 52 // immediately with no actual work having been done by the workers. 53 ///////////////////// 54 // Implementatiuon notes: remove before checking XXX 55 /* 56 Each gang is working on a task at a certain time. 57 Some subset of workers may have yielded and some may 58 have finished their quota of work. Until this task has 59 been completed, the workers are bound to that task. 60 Once the task has been completed, the gang unbounds 61 itself from the task. 62 63 The yielding work gang thus exports two invokation 64 interfaces: run_task() and continue_task(). The 275 } 276 277 /////////////////////////////// 278 // YieldingFlexibleGangTask 279 /////////////////////////////// 280 void YieldingFlexibleGangTask::yield() { 281 assert(gang() != NULL, "No gang to signal"); 282 gang()->yield(); 283 } 284 285 void YieldingFlexibleGangTask::abort() { 286 assert(gang() != NULL, "No gang to signal"); 287 gang()->abort(); 288 } 289 290 /////////////////////////////// 291 // YieldingFlexibleGangWorker 292 /////////////////////////////// 293 void YieldingFlexibleGangWorker::loop() { 294 int previous_sequence_number = 0; 295 Monitor* gang_monitor = gang()->monitor(); 296 MutexLockerEx ml(gang_monitor, Mutex::_no_safepoint_check_flag); 297 WorkData data; 298 int id; 299 while (true) { 300 // Check if there is work to do. 301 gang()->internal_worker_poll(&data); 302 if (data.task() != NULL && data.sequence_number() != previous_sequence_number) { 303 // There is work to be done. 304 // First check if we need to become active or if there 305 // are already the requisite number of workers 306 if (gang()->started_workers() == yf_gang()->active_workers()) { 307 // There are already enough workers, we do not need to 308 // to run; fall through and wait on monitor. 309 } else { 310 // We need to pitch in and do the work. 311 assert(gang()->started_workers() < yf_gang()->active_workers(), 312 "Unexpected state"); 313 id = gang()->started_workers(); 314 gang()->internal_note_start(); 315 // Now, release the gang mutex and do the work. 316 { 317 MutexUnlockerEx mul(gang_monitor, Mutex::_no_safepoint_check_flag); 318 data.task()->work(id); // This might include yielding 319 } 320 // Reacquire monitor and note completion of this worker 321 gang()->internal_note_finish(); 322 // Update status of task based on whether all workers have 323 // finished or some have yielded 324 assert(data.task() == gang()->task(), "Confused task binding"); 325 if (gang()->finished_workers() == yf_gang()->active_workers()) { 326 switch (data.yf_task()->status()) { 327 case ABORTING: { 328 data.yf_task()->set_status(ABORTED); 329 break; 330 } 331 case ACTIVE: 332 case COMPLETING: { 333 data.yf_task()->set_status(COMPLETED); 334 break; 335 } 336 default: 337 ShouldNotReachHere(); 338 } 339 gang_monitor->notify_all(); // Notify overseer 340 } else { // at least one worker is still working or yielded 341 assert(gang()->finished_workers() < yf_gang()->active_workers(), 342 "Counts inconsistent"); 343 switch (data.yf_task()->status()) { 344 case ACTIVE: { 345 // first, but not only thread to complete 346 data.yf_task()->set_status(COMPLETING); 347 break; 348 } 349 case YIELDING: { 350 if (gang()->finished_workers() + yf_gang()->yielded_workers() 351 == yf_gang()->active_workers()) { 352 data.yf_task()->set_status(YIELDED); 353 gang_monitor->notify_all(); // notify overseer 354 } 355 break; 356 } 357 case ABORTING: 358 case COMPLETING: { 359 break; // nothing to do 360 } 361 default: // everything else: INACTIVE, YIELDED, ABORTED, COMPLETED 362 ShouldNotReachHere(); 363 } 364 } 365 } 366 } 367 // Remember the sequence number 368 previous_sequence_number = data.sequence_number(); 369 // Wait for more work 370 gang_monitor->wait(Mutex::_no_safepoint_check_flag); | 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 "utilities/macros.hpp" 28 29 YieldingFlexibleGangWorker::YieldingFlexibleGangWorker(YieldingFlexibleWorkGang* gang, int id) 30 : AbstractGangWorker(gang, id) {} 31 32 YieldingFlexibleWorkGang::YieldingFlexibleWorkGang( 33 const char* name, uint workers, bool are_GC_task_threads) : 34 AbstractWorkGang(name, workers, are_GC_task_threads, false), 35 _yielded_workers(0), 36 _started_workers(0), 37 _finished_workers(0), 38 _sequence_number(0), 39 _task(NULL) { 40 41 // Other initialization. 42 _monitor = new Monitor(/* priority */ Mutex::leaf, 43 /* name */ "WorkGroup monitor", 44 /* allow_vm_block */ are_GC_task_threads, 45 Monitor::_safepoint_check_sometimes); 46 47 assert(monitor() != NULL, "Failed to allocate monitor"); 48 } 49 50 AbstractGangWorker* YieldingFlexibleWorkGang::allocate_worker(uint which) { 51 YieldingFlexibleGangWorker* new_member = 52 new YieldingFlexibleGangWorker(this, which); 53 return (YieldingFlexibleGangWorker*) new_member; 54 } 55 56 void YieldingFlexibleWorkGang::internal_worker_poll(YieldingWorkData* data) const { 57 assert(data != NULL, "worker data is null"); 58 data->set_task(task()); 59 data->set_sequence_number(sequence_number()); 60 } 61 62 void YieldingFlexibleWorkGang::internal_note_start() { 63 assert(monitor()->owned_by_self(), "note_finish is an internal method"); 64 _started_workers += 1; 65 } 66 67 void YieldingFlexibleWorkGang::internal_note_finish() { 68 assert(monitor()->owned_by_self(), "note_finish is an internal method"); 69 _finished_workers += 1; 70 } 71 72 // Run a task; returns when the task is done, or the workers yield, 73 // or the task is aborted. 74 // A task that has been yielded can be continued via this interface 75 // by using the same task repeatedly as the argument to the call. 76 // It is expected that the YieldingFlexibleGangTask carries the appropriate 77 // continuation information used by workers to continue the task 78 // from its last yield point. Thus, a completed task will return 79 // immediately with no actual work having been done by the workers. 80 ///////////////////// 81 // Implementatiuon notes: remove before checking XXX 82 /* 83 Each gang is working on a task at a certain time. 84 Some subset of workers may have yielded and some may 85 have finished their quota of work. Until this task has 86 been completed, the workers are bound to that task. 87 Once the task has been completed, the gang unbounds 88 itself from the task. 89 90 The yielding work gang thus exports two invokation 91 interfaces: run_task() and continue_task(). The 302 } 303 304 /////////////////////////////// 305 // YieldingFlexibleGangTask 306 /////////////////////////////// 307 void YieldingFlexibleGangTask::yield() { 308 assert(gang() != NULL, "No gang to signal"); 309 gang()->yield(); 310 } 311 312 void YieldingFlexibleGangTask::abort() { 313 assert(gang() != NULL, "No gang to signal"); 314 gang()->abort(); 315 } 316 317 /////////////////////////////// 318 // YieldingFlexibleGangWorker 319 /////////////////////////////// 320 void YieldingFlexibleGangWorker::loop() { 321 int previous_sequence_number = 0; 322 Monitor* gang_monitor = yf_gang()->monitor(); 323 MutexLockerEx ml(gang_monitor, Mutex::_no_safepoint_check_flag); 324 YieldingWorkData data; 325 int id; 326 while (true) { 327 // Check if there is work to do. 328 yf_gang()->internal_worker_poll(&data); 329 if (data.task() != NULL && data.sequence_number() != previous_sequence_number) { 330 // There is work to be done. 331 // First check if we need to become active or if there 332 // are already the requisite number of workers 333 if (yf_gang()->started_workers() == yf_gang()->active_workers()) { 334 // There are already enough workers, we do not need to 335 // to run; fall through and wait on monitor. 336 } else { 337 // We need to pitch in and do the work. 338 assert(yf_gang()->started_workers() < yf_gang()->active_workers(), 339 "Unexpected state"); 340 id = yf_gang()->started_workers(); 341 yf_gang()->internal_note_start(); 342 // Now, release the gang mutex and do the work. 343 { 344 MutexUnlockerEx mul(gang_monitor, Mutex::_no_safepoint_check_flag); 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(Mutex::_no_safepoint_check_flag); |