< prev index next >

src/share/vm/gc/cms/yieldingWorkgroup.cpp

Print this page




   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);
< prev index next >