src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp

Mon, 01 Dec 2008 23:25:24 -0800

author
ysr
date
Mon, 01 Dec 2008 23:25:24 -0800
changeset 892
27a80744a83b
parent 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

6778647: snap(), snap_policy() should be renamed setup(), setup_policy()
Summary: Renamed Reference{Policy,Pocessor} methods from snap{,_policy}() to setup{,_policy}()
Reviewed-by: apetrusenko

     1 /*
     2  * Copyright 2002-2007 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 #include "incls/_precompiled.incl"
    26 #include "incls/_gcTaskManager.cpp.incl"
    28 //
    29 // GCTask
    30 //
    32 const char* GCTask::Kind::to_string(kind value) {
    33   const char* result = "unknown GCTask kind";
    34   switch (value) {
    35   default:
    36     result = "unknown GCTask kind";
    37     break;
    38   case unknown_task:
    39     result = "unknown task";
    40     break;
    41   case ordinary_task:
    42     result = "ordinary task";
    43     break;
    44   case barrier_task:
    45     result = "barrier task";
    46     break;
    47   case noop_task:
    48     result = "noop task";
    49     break;
    50   }
    51   return result;
    52 };
    54 GCTask::GCTask() :
    55   _kind(Kind::ordinary_task),
    56   _affinity(GCTaskManager::sentinel_worker()){
    57   initialize();
    58 }
    60 GCTask::GCTask(Kind::kind kind) :
    61   _kind(kind),
    62   _affinity(GCTaskManager::sentinel_worker()) {
    63   initialize();
    64 }
    66 GCTask::GCTask(uint affinity) :
    67   _kind(Kind::ordinary_task),
    68   _affinity(affinity) {
    69   initialize();
    70 }
    72 GCTask::GCTask(Kind::kind kind, uint affinity) :
    73   _kind(kind),
    74   _affinity(affinity) {
    75   initialize();
    76 }
    78 void GCTask::initialize() {
    79   _older = NULL;
    80   _newer = NULL;
    81 }
    83 void GCTask::destruct() {
    84   assert(older() == NULL, "shouldn't have an older task");
    85   assert(newer() == NULL, "shouldn't have a newer task");
    86   // Nothing to do.
    87 }
    89 NOT_PRODUCT(
    90 void GCTask::print(const char* message) const {
    91   tty->print(INTPTR_FORMAT " <- " INTPTR_FORMAT "(%u) -> " INTPTR_FORMAT,
    92              newer(), this, affinity(), older());
    93 }
    94 )
    96 //
    97 // GCTaskQueue
    98 //
   100 GCTaskQueue* GCTaskQueue::create() {
   101   GCTaskQueue* result = new GCTaskQueue(false);
   102   if (TraceGCTaskQueue) {
   103     tty->print_cr("GCTaskQueue::create()"
   104                   " returns " INTPTR_FORMAT, result);
   105   }
   106   return result;
   107 }
   109 GCTaskQueue* GCTaskQueue::create_on_c_heap() {
   110   GCTaskQueue* result = new(ResourceObj::C_HEAP) GCTaskQueue(true);
   111   if (TraceGCTaskQueue) {
   112     tty->print_cr("GCTaskQueue::create_on_c_heap()"
   113                   " returns " INTPTR_FORMAT,
   114                   result);
   115   }
   116   return result;
   117 }
   119 GCTaskQueue::GCTaskQueue(bool on_c_heap) :
   120   _is_c_heap_obj(on_c_heap) {
   121   initialize();
   122   if (TraceGCTaskQueue) {
   123     tty->print_cr("[" INTPTR_FORMAT "]"
   124                   " GCTaskQueue::GCTaskQueue() constructor",
   125                   this);
   126   }
   127 }
   129 void GCTaskQueue::destruct() {
   130   // Nothing to do.
   131 }
   133 void GCTaskQueue::destroy(GCTaskQueue* that) {
   134   if (TraceGCTaskQueue) {
   135     tty->print_cr("[" INTPTR_FORMAT "]"
   136                   " GCTaskQueue::destroy()"
   137                   "  is_c_heap_obj:  %s",
   138                   that,
   139                   that->is_c_heap_obj() ? "true" : "false");
   140   }
   141   // That instance may have been allocated as a CHeapObj,
   142   // in which case we have to free it explicitly.
   143   if (that != NULL) {
   144     that->destruct();
   145     assert(that->is_empty(), "should be empty");
   146     if (that->is_c_heap_obj()) {
   147       FreeHeap(that);
   148     }
   149   }
   150 }
   152 void GCTaskQueue::initialize() {
   153   set_insert_end(NULL);
   154   set_remove_end(NULL);
   155   set_length(0);
   156 }
   158 // Enqueue one task.
   159 void GCTaskQueue::enqueue(GCTask* task) {
   160   if (TraceGCTaskQueue) {
   161     tty->print_cr("[" INTPTR_FORMAT "]"
   162                   " GCTaskQueue::enqueue(task: "
   163                   INTPTR_FORMAT ")",
   164                   this, task);
   165     print("before:");
   166   }
   167   assert(task != NULL, "shouldn't have null task");
   168   assert(task->older() == NULL, "shouldn't be on queue");
   169   assert(task->newer() == NULL, "shouldn't be on queue");
   170   task->set_newer(NULL);
   171   task->set_older(insert_end());
   172   if (is_empty()) {
   173     set_remove_end(task);
   174   } else {
   175     insert_end()->set_newer(task);
   176   }
   177   set_insert_end(task);
   178   increment_length();
   179   if (TraceGCTaskQueue) {
   180     print("after:");
   181   }
   182 }
   184 // Enqueue a whole list of tasks.  Empties the argument list.
   185 void GCTaskQueue::enqueue(GCTaskQueue* list) {
   186   if (TraceGCTaskQueue) {
   187     tty->print_cr("[" INTPTR_FORMAT "]"
   188                   " GCTaskQueue::enqueue(list: "
   189                   INTPTR_FORMAT ")",
   190                   this);
   191     print("before:");
   192     list->print("list:");
   193   }
   194   if (list->is_empty()) {
   195     // Enqueuing the empty list: nothing to do.
   196     return;
   197   }
   198   uint list_length = list->length();
   199   if (is_empty()) {
   200     // Enqueuing to empty list: just acquire elements.
   201     set_insert_end(list->insert_end());
   202     set_remove_end(list->remove_end());
   203     set_length(list_length);
   204   } else {
   205     // Prepend argument list to our queue.
   206     list->remove_end()->set_older(insert_end());
   207     insert_end()->set_newer(list->remove_end());
   208     set_insert_end(list->insert_end());
   209     // empty the argument list.
   210   }
   211   set_length(length() + list_length);
   212   list->initialize();
   213   if (TraceGCTaskQueue) {
   214     print("after:");
   215     list->print("list:");
   216   }
   217 }
   219 // Dequeue one task.
   220 GCTask* GCTaskQueue::dequeue() {
   221   if (TraceGCTaskQueue) {
   222     tty->print_cr("[" INTPTR_FORMAT "]"
   223                   " GCTaskQueue::dequeue()", this);
   224     print("before:");
   225   }
   226   assert(!is_empty(), "shouldn't dequeue from empty list");
   227   GCTask* result = remove();
   228   assert(result != NULL, "shouldn't have NULL task");
   229   if (TraceGCTaskQueue) {
   230     tty->print_cr("    return: " INTPTR_FORMAT, result);
   231     print("after:");
   232   }
   233   return result;
   234 }
   236 // Dequeue one task, preferring one with affinity.
   237 GCTask* GCTaskQueue::dequeue(uint affinity) {
   238   if (TraceGCTaskQueue) {
   239     tty->print_cr("[" INTPTR_FORMAT "]"
   240                   " GCTaskQueue::dequeue(%u)", this, affinity);
   241     print("before:");
   242   }
   243   assert(!is_empty(), "shouldn't dequeue from empty list");
   244   // Look down to the next barrier for a task with this affinity.
   245   GCTask* result = NULL;
   246   for (GCTask* element = remove_end();
   247        element != NULL;
   248        element = element->newer()) {
   249     if (element->is_barrier_task()) {
   250       // Don't consider barrier tasks, nor past them.
   251       result = NULL;
   252       break;
   253     }
   254     if (element->affinity() == affinity) {
   255       result = remove(element);
   256       break;
   257     }
   258   }
   259   // If we didn't find anything with affinity, just take the next task.
   260   if (result == NULL) {
   261     result = remove();
   262   }
   263   if (TraceGCTaskQueue) {
   264     tty->print_cr("    return: " INTPTR_FORMAT, result);
   265     print("after:");
   266   }
   267   return result;
   268 }
   270 GCTask* GCTaskQueue::remove() {
   271   // Dequeue from remove end.
   272   GCTask* result = remove_end();
   273   assert(result != NULL, "shouldn't have null task");
   274   assert(result->older() == NULL, "not the remove_end");
   275   set_remove_end(result->newer());
   276   if (remove_end() == NULL) {
   277     assert(insert_end() == result, "not a singleton");
   278     set_insert_end(NULL);
   279   } else {
   280     remove_end()->set_older(NULL);
   281   }
   282   result->set_newer(NULL);
   283   decrement_length();
   284   assert(result->newer() == NULL, "shouldn't be on queue");
   285   assert(result->older() == NULL, "shouldn't be on queue");
   286   return result;
   287 }
   289 GCTask* GCTaskQueue::remove(GCTask* task) {
   290   // This is slightly more work, and has slightly fewer asserts
   291   // than removing from the remove end.
   292   assert(task != NULL, "shouldn't have null task");
   293   GCTask* result = task;
   294   if (result->newer() != NULL) {
   295     result->newer()->set_older(result->older());
   296   } else {
   297     assert(insert_end() == result, "not youngest");
   298     set_insert_end(result->older());
   299   }
   300   if (result->older() != NULL) {
   301     result->older()->set_newer(result->newer());
   302   } else {
   303     assert(remove_end() == result, "not oldest");
   304     set_remove_end(result->newer());
   305   }
   306   result->set_newer(NULL);
   307   result->set_older(NULL);
   308   decrement_length();
   309   return result;
   310 }
   312 NOT_PRODUCT(
   313 void GCTaskQueue::print(const char* message) const {
   314   tty->print_cr("[" INTPTR_FORMAT "] GCTaskQueue:"
   315                 "  insert_end: " INTPTR_FORMAT
   316                 "  remove_end: " INTPTR_FORMAT
   317                 "  %s",
   318                 this, insert_end(), remove_end(), message);
   319   for (GCTask* element = insert_end();
   320        element != NULL;
   321        element = element->older()) {
   322     element->print("    ");
   323     tty->cr();
   324   }
   325 }
   326 )
   328 //
   329 // SynchronizedGCTaskQueue
   330 //
   332 SynchronizedGCTaskQueue::SynchronizedGCTaskQueue(GCTaskQueue* queue_arg,
   333                                                  Monitor *       lock_arg) :
   334   _unsynchronized_queue(queue_arg),
   335   _lock(lock_arg) {
   336   assert(unsynchronized_queue() != NULL, "null queue");
   337   assert(lock() != NULL, "null lock");
   338 }
   340 SynchronizedGCTaskQueue::~SynchronizedGCTaskQueue() {
   341   // Nothing to do.
   342 }
   344 //
   345 // GCTaskManager
   346 //
   347 GCTaskManager::GCTaskManager(uint workers) :
   348   _workers(workers),
   349   _ndc(NULL) {
   350   initialize();
   351 }
   353 GCTaskManager::GCTaskManager(uint workers, NotifyDoneClosure* ndc) :
   354   _workers(workers),
   355   _ndc(ndc) {
   356   initialize();
   357 }
   359 void GCTaskManager::initialize() {
   360   if (TraceGCTaskManager) {
   361     tty->print_cr("GCTaskManager::initialize: workers: %u", workers());
   362   }
   363   assert(workers() != 0, "no workers");
   364   _monitor = new Monitor(Mutex::barrier,                // rank
   365                          "GCTaskManager monitor",       // name
   366                          Mutex::_allow_vm_block_flag);  // allow_vm_block
   367   // The queue for the GCTaskManager must be a CHeapObj.
   368   GCTaskQueue* unsynchronized_queue = GCTaskQueue::create_on_c_heap();
   369   _queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
   370   _noop_task = NoopGCTask::create_on_c_heap();
   371   _resource_flag = NEW_C_HEAP_ARRAY(bool, workers());
   372   {
   373     // Set up worker threads.
   374     //     Distribute the workers among the available processors,
   375     //     unless we were told not to, or if the os doesn't want to.
   376     uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers());
   377     if (!BindGCTaskThreadsToCPUs ||
   378         !os::distribute_processes(workers(), processor_assignment)) {
   379       for (uint a = 0; a < workers(); a += 1) {
   380         processor_assignment[a] = sentinel_worker();
   381       }
   382     }
   383     _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers());
   384     for (uint t = 0; t < workers(); t += 1) {
   385       set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
   386     }
   387     if (TraceGCTaskThread) {
   388       tty->print("GCTaskManager::initialize: distribution:");
   389       for (uint t = 0; t < workers(); t += 1) {
   390         tty->print("  %u", processor_assignment[t]);
   391       }
   392       tty->cr();
   393     }
   394     FREE_C_HEAP_ARRAY(uint, processor_assignment);
   395   }
   396   reset_busy_workers();
   397   set_unblocked();
   398   for (uint w = 0; w < workers(); w += 1) {
   399     set_resource_flag(w, false);
   400   }
   401   reset_delivered_tasks();
   402   reset_completed_tasks();
   403   reset_noop_tasks();
   404   reset_barriers();
   405   reset_emptied_queue();
   406   for (uint s = 0; s < workers(); s += 1) {
   407     thread(s)->start();
   408   }
   409 }
   411 GCTaskManager::~GCTaskManager() {
   412   assert(busy_workers() == 0, "still have busy workers");
   413   assert(queue()->is_empty(), "still have queued work");
   414   NoopGCTask::destroy(_noop_task);
   415   _noop_task = NULL;
   416   if (_thread != NULL) {
   417     for (uint i = 0; i < workers(); i += 1) {
   418       GCTaskThread::destroy(thread(i));
   419       set_thread(i, NULL);
   420     }
   421     FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
   422     _thread = NULL;
   423   }
   424   if (_resource_flag != NULL) {
   425     FREE_C_HEAP_ARRAY(bool, _resource_flag);
   426     _resource_flag = NULL;
   427   }
   428   if (queue() != NULL) {
   429     GCTaskQueue* unsynchronized_queue = queue()->unsynchronized_queue();
   430     GCTaskQueue::destroy(unsynchronized_queue);
   431     SynchronizedGCTaskQueue::destroy(queue());
   432     _queue = NULL;
   433   }
   434   if (monitor() != NULL) {
   435     delete monitor();
   436     _monitor = NULL;
   437   }
   438 }
   440 void GCTaskManager::print_task_time_stamps() {
   441   for(uint i=0; i<ParallelGCThreads; i++) {
   442     GCTaskThread* t = thread(i);
   443     t->print_task_time_stamps();
   444   }
   445 }
   447 void GCTaskManager::print_threads_on(outputStream* st) {
   448   uint num_thr = workers();
   449   for (uint i = 0; i < num_thr; i++) {
   450     thread(i)->print_on(st);
   451     st->cr();
   452   }
   453 }
   455 void GCTaskManager::threads_do(ThreadClosure* tc) {
   456   assert(tc != NULL, "Null ThreadClosure");
   457   uint num_thr = workers();
   458   for (uint i = 0; i < num_thr; i++) {
   459     tc->do_thread(thread(i));
   460   }
   461 }
   463 GCTaskThread* GCTaskManager::thread(uint which) {
   464   assert(which < workers(), "index out of bounds");
   465   assert(_thread[which] != NULL, "shouldn't have null thread");
   466   return _thread[which];
   467 }
   469 void GCTaskManager::set_thread(uint which, GCTaskThread* value) {
   470   assert(which < workers(), "index out of bounds");
   471   assert(value != NULL, "shouldn't have null thread");
   472   _thread[which] = value;
   473 }
   475 void GCTaskManager::add_task(GCTask* task) {
   476   assert(task != NULL, "shouldn't have null task");
   477   MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   478   if (TraceGCTaskManager) {
   479     tty->print_cr("GCTaskManager::add_task(" INTPTR_FORMAT " [%s])",
   480                   task, GCTask::Kind::to_string(task->kind()));
   481   }
   482   queue()->enqueue(task);
   483   // Notify with the lock held to avoid missed notifies.
   484   if (TraceGCTaskManager) {
   485     tty->print_cr("    GCTaskManager::add_task (%s)->notify_all",
   486                   monitor()->name());
   487   }
   488   (void) monitor()->notify_all();
   489   // Release monitor().
   490 }
   492 void GCTaskManager::add_list(GCTaskQueue* list) {
   493   assert(list != NULL, "shouldn't have null task");
   494   MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   495   if (TraceGCTaskManager) {
   496     tty->print_cr("GCTaskManager::add_list(%u)", list->length());
   497   }
   498   queue()->enqueue(list);
   499   // Notify with the lock held to avoid missed notifies.
   500   if (TraceGCTaskManager) {
   501     tty->print_cr("    GCTaskManager::add_list (%s)->notify_all",
   502                   monitor()->name());
   503   }
   504   (void) monitor()->notify_all();
   505   // Release monitor().
   506 }
   508 GCTask* GCTaskManager::get_task(uint which) {
   509   GCTask* result = NULL;
   510   // Grab the queue lock.
   511   MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   512   // Wait while the queue is block or
   513   // there is nothing to do, except maybe release resources.
   514   while (is_blocked() ||
   515          (queue()->is_empty() && !should_release_resources(which))) {
   516     if (TraceGCTaskManager) {
   517       tty->print_cr("GCTaskManager::get_task(%u)"
   518                     "  blocked: %s"
   519                     "  empty: %s"
   520                     "  release: %s",
   521                     which,
   522                     is_blocked() ? "true" : "false",
   523                     queue()->is_empty() ? "true" : "false",
   524                     should_release_resources(which) ? "true" : "false");
   525       tty->print_cr("    => (%s)->wait()",
   526                     monitor()->name());
   527     }
   528     monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
   529   }
   530   // We've reacquired the queue lock here.
   531   // Figure out which condition caused us to exit the loop above.
   532   if (!queue()->is_empty()) {
   533     if (UseGCTaskAffinity) {
   534       result = queue()->dequeue(which);
   535     } else {
   536       result = queue()->dequeue();
   537     }
   538     if (result->is_barrier_task()) {
   539       assert(which != sentinel_worker(),
   540              "blocker shouldn't be bogus");
   541       set_blocking_worker(which);
   542     }
   543   } else {
   544     // The queue is empty, but we were woken up.
   545     // Just hand back a Noop task,
   546     // in case someone wanted us to release resources, or whatever.
   547     result = noop_task();
   548     increment_noop_tasks();
   549   }
   550   assert(result != NULL, "shouldn't have null task");
   551   if (TraceGCTaskManager) {
   552     tty->print_cr("GCTaskManager::get_task(%u) => " INTPTR_FORMAT " [%s]",
   553                   which, result, GCTask::Kind::to_string(result->kind()));
   554     tty->print_cr("     %s", result->name());
   555   }
   556   increment_busy_workers();
   557   increment_delivered_tasks();
   558   return result;
   559   // Release monitor().
   560 }
   562 void GCTaskManager::note_completion(uint which) {
   563   MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   564   if (TraceGCTaskManager) {
   565     tty->print_cr("GCTaskManager::note_completion(%u)", which);
   566   }
   567   // If we are blocked, check if the completing thread is the blocker.
   568   if (blocking_worker() == which) {
   569     assert(blocking_worker() != sentinel_worker(),
   570            "blocker shouldn't be bogus");
   571     increment_barriers();
   572     set_unblocked();
   573   }
   574   increment_completed_tasks();
   575   uint active = decrement_busy_workers();
   576   if ((active == 0) && (queue()->is_empty())) {
   577     increment_emptied_queue();
   578     if (TraceGCTaskManager) {
   579       tty->print_cr("    GCTaskManager::note_completion(%u) done", which);
   580     }
   581     // Notify client that we are done.
   582     NotifyDoneClosure* ndc = notify_done_closure();
   583     if (ndc != NULL) {
   584       ndc->notify(this);
   585     }
   586   }
   587   if (TraceGCTaskManager) {
   588     tty->print_cr("    GCTaskManager::note_completion(%u) (%s)->notify_all",
   589                   which, monitor()->name());
   590     tty->print_cr("  "
   591                   "  blocked: %s"
   592                   "  empty: %s"
   593                   "  release: %s",
   594                   is_blocked() ? "true" : "false",
   595                   queue()->is_empty() ? "true" : "false",
   596                   should_release_resources(which) ? "true" : "false");
   597     tty->print_cr("  "
   598                   "  delivered: %u"
   599                   "  completed: %u"
   600                   "  barriers: %u"
   601                   "  emptied: %u",
   602                   delivered_tasks(),
   603                   completed_tasks(),
   604                   barriers(),
   605                   emptied_queue());
   606   }
   607   // Tell everyone that a task has completed.
   608   (void) monitor()->notify_all();
   609   // Release monitor().
   610 }
   612 uint GCTaskManager::increment_busy_workers() {
   613   assert(queue()->own_lock(), "don't own the lock");
   614   _busy_workers += 1;
   615   return _busy_workers;
   616 }
   618 uint GCTaskManager::decrement_busy_workers() {
   619   assert(queue()->own_lock(), "don't own the lock");
   620   _busy_workers -= 1;
   621   return _busy_workers;
   622 }
   624 void GCTaskManager::release_all_resources() {
   625   // If you want this to be done atomically, do it in a BarrierGCTask.
   626   for (uint i = 0; i < workers(); i += 1) {
   627     set_resource_flag(i, true);
   628   }
   629 }
   631 bool GCTaskManager::should_release_resources(uint which) {
   632   // This can be done without a lock because each thread reads one element.
   633   return resource_flag(which);
   634 }
   636 void GCTaskManager::note_release(uint which) {
   637   // This can be done without a lock because each thread writes one element.
   638   set_resource_flag(which, false);
   639 }
   641 void GCTaskManager::execute_and_wait(GCTaskQueue* list) {
   642   WaitForBarrierGCTask* fin = WaitForBarrierGCTask::create();
   643   list->enqueue(fin);
   644   add_list(list);
   645   fin->wait_for();
   646   // We have to release the barrier tasks!
   647   WaitForBarrierGCTask::destroy(fin);
   648 }
   650 bool GCTaskManager::resource_flag(uint which) {
   651   assert(which < workers(), "index out of bounds");
   652   return _resource_flag[which];
   653 }
   655 void GCTaskManager::set_resource_flag(uint which, bool value) {
   656   assert(which < workers(), "index out of bounds");
   657   _resource_flag[which] = value;
   658 }
   660 //
   661 // NoopGCTask
   662 //
   664 NoopGCTask* NoopGCTask::create() {
   665   NoopGCTask* result = new NoopGCTask(false);
   666   return result;
   667 }
   669 NoopGCTask* NoopGCTask::create_on_c_heap() {
   670   NoopGCTask* result = new(ResourceObj::C_HEAP) NoopGCTask(true);
   671   return result;
   672 }
   674 void NoopGCTask::destroy(NoopGCTask* that) {
   675   if (that != NULL) {
   676     that->destruct();
   677     if (that->is_c_heap_obj()) {
   678       FreeHeap(that);
   679     }
   680   }
   681 }
   683 void NoopGCTask::destruct() {
   684   // This has to know it's superclass structure, just like the constructor.
   685   this->GCTask::destruct();
   686   // Nothing else to do.
   687 }
   689 //
   690 // BarrierGCTask
   691 //
   693 void BarrierGCTask::do_it(GCTaskManager* manager, uint which) {
   694   // Wait for this to be the only busy worker.
   695   // ??? I thought of having a StackObj class
   696   //     whose constructor would grab the lock and come to the barrier,
   697   //     and whose destructor would release the lock,
   698   //     but that seems like too much mechanism for two lines of code.
   699   MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
   700   do_it_internal(manager, which);
   701   // Release manager->lock().
   702 }
   704 void BarrierGCTask::do_it_internal(GCTaskManager* manager, uint which) {
   705   // Wait for this to be the only busy worker.
   706   assert(manager->monitor()->owned_by_self(), "don't own the lock");
   707   assert(manager->is_blocked(), "manager isn't blocked");
   708   while (manager->busy_workers() > 1) {
   709     if (TraceGCTaskManager) {
   710       tty->print_cr("BarrierGCTask::do_it(%u) waiting on %u workers",
   711                     which, manager->busy_workers());
   712     }
   713     manager->monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
   714   }
   715 }
   717 void BarrierGCTask::destruct() {
   718   this->GCTask::destruct();
   719   // Nothing else to do.
   720 }
   722 //
   723 // ReleasingBarrierGCTask
   724 //
   726 void ReleasingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
   727   MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
   728   do_it_internal(manager, which);
   729   manager->release_all_resources();
   730   // Release manager->lock().
   731 }
   733 void ReleasingBarrierGCTask::destruct() {
   734   this->BarrierGCTask::destruct();
   735   // Nothing else to do.
   736 }
   738 //
   739 // NotifyingBarrierGCTask
   740 //
   742 void NotifyingBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
   743   MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
   744   do_it_internal(manager, which);
   745   NotifyDoneClosure* ndc = notify_done_closure();
   746   if (ndc != NULL) {
   747     ndc->notify(manager);
   748   }
   749   // Release manager->lock().
   750 }
   752 void NotifyingBarrierGCTask::destruct() {
   753   this->BarrierGCTask::destruct();
   754   // Nothing else to do.
   755 }
   757 //
   758 // WaitForBarrierGCTask
   759 //
   760 WaitForBarrierGCTask* WaitForBarrierGCTask::create() {
   761   WaitForBarrierGCTask* result = new WaitForBarrierGCTask(false);
   762   return result;
   763 }
   765 WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() {
   766   WaitForBarrierGCTask* result = new WaitForBarrierGCTask(true);
   767   return result;
   768 }
   770 WaitForBarrierGCTask::WaitForBarrierGCTask(bool on_c_heap) :
   771   _is_c_heap_obj(on_c_heap) {
   772   _monitor = MonitorSupply::reserve();
   773   set_should_wait(true);
   774   if (TraceGCTaskManager) {
   775     tty->print_cr("[" INTPTR_FORMAT "]"
   776                   " WaitForBarrierGCTask::WaitForBarrierGCTask()"
   777                   "  monitor: " INTPTR_FORMAT,
   778                   this, monitor());
   779   }
   780 }
   782 void WaitForBarrierGCTask::destroy(WaitForBarrierGCTask* that) {
   783   if (that != NULL) {
   784     if (TraceGCTaskManager) {
   785       tty->print_cr("[" INTPTR_FORMAT "]"
   786                     " WaitForBarrierGCTask::destroy()"
   787                     "  is_c_heap_obj: %s"
   788                     "  monitor: " INTPTR_FORMAT,
   789                     that,
   790                     that->is_c_heap_obj() ? "true" : "false",
   791                     that->monitor());
   792     }
   793     that->destruct();
   794     if (that->is_c_heap_obj()) {
   795       FreeHeap(that);
   796     }
   797   }
   798 }
   800 void WaitForBarrierGCTask::destruct() {
   801   assert(monitor() != NULL, "monitor should not be NULL");
   802   if (TraceGCTaskManager) {
   803     tty->print_cr("[" INTPTR_FORMAT "]"
   804                   " WaitForBarrierGCTask::destruct()"
   805                   "  monitor: " INTPTR_FORMAT,
   806                   this, monitor());
   807   }
   808   this->BarrierGCTask::destruct();
   809   // Clean up that should be in the destructor,
   810   // except that ResourceMarks don't call destructors.
   811    if (monitor() != NULL) {
   812      MonitorSupply::release(monitor());
   813   }
   814   _monitor = (Monitor*) 0xDEAD000F;
   815 }
   817 void WaitForBarrierGCTask::do_it(GCTaskManager* manager, uint which) {
   818   if (TraceGCTaskManager) {
   819     tty->print_cr("[" INTPTR_FORMAT "]"
   820                   " WaitForBarrierGCTask::do_it() waiting for idle"
   821                   "  monitor: " INTPTR_FORMAT,
   822                   this, monitor());
   823   }
   824   {
   825     // First, wait for the barrier to arrive.
   826     MutexLockerEx ml(manager->lock(), Mutex::_no_safepoint_check_flag);
   827     do_it_internal(manager, which);
   828     // Release manager->lock().
   829   }
   830   {
   831     // Then notify the waiter.
   832     MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   833     set_should_wait(false);
   834     // Waiter doesn't miss the notify in the wait_for method
   835     // since it checks the flag after grabbing the monitor.
   836     if (TraceGCTaskManager) {
   837       tty->print_cr("[" INTPTR_FORMAT "]"
   838                     " WaitForBarrierGCTask::do_it()"
   839                     "  [" INTPTR_FORMAT "] (%s)->notify_all()",
   840                     this, monitor(), monitor()->name());
   841     }
   842     monitor()->notify_all();
   843     // Release monitor().
   844   }
   845 }
   847 void WaitForBarrierGCTask::wait_for() {
   848   if (TraceGCTaskManager) {
   849     tty->print_cr("[" INTPTR_FORMAT "]"
   850                   " WaitForBarrierGCTask::wait_for()"
   851       "  should_wait: %s",
   852       this, should_wait() ? "true" : "false");
   853   }
   854   {
   855     // Grab the lock and check again.
   856     MutexLockerEx ml(monitor(), Mutex::_no_safepoint_check_flag);
   857     while (should_wait()) {
   858       if (TraceGCTaskManager) {
   859         tty->print_cr("[" INTPTR_FORMAT "]"
   860                       " WaitForBarrierGCTask::wait_for()"
   861           "  [" INTPTR_FORMAT "] (%s)->wait()",
   862           this, monitor(), monitor()->name());
   863       }
   864       monitor()->wait(Mutex::_no_safepoint_check_flag, 0);
   865     }
   866     // Reset the flag in case someone reuses this task.
   867     set_should_wait(true);
   868     if (TraceGCTaskManager) {
   869       tty->print_cr("[" INTPTR_FORMAT "]"
   870                     " WaitForBarrierGCTask::wait_for() returns"
   871         "  should_wait: %s",
   872         this, should_wait() ? "true" : "false");
   873     }
   874     // Release monitor().
   875   }
   876 }
   878 Mutex*                   MonitorSupply::_lock     = NULL;
   879 GrowableArray<Monitor*>* MonitorSupply::_freelist = NULL;
   881 Monitor* MonitorSupply::reserve() {
   882   Monitor* result = NULL;
   883   // Lazy initialization: possible race.
   884   if (lock() == NULL) {
   885     _lock = new Mutex(Mutex::barrier,                  // rank
   886                       "MonitorSupply mutex",           // name
   887                       Mutex::_allow_vm_block_flag);    // allow_vm_block
   888   }
   889   {
   890     MutexLockerEx ml(lock());
   891     // Lazy initialization.
   892     if (freelist() == NULL) {
   893       _freelist =
   894         new(ResourceObj::C_HEAP) GrowableArray<Monitor*>(ParallelGCThreads,
   895                                                          true);
   896     }
   897     if (! freelist()->is_empty()) {
   898       result = freelist()->pop();
   899     } else {
   900       result = new Monitor(Mutex::barrier,                  // rank
   901                            "MonitorSupply monitor",         // name
   902                            Mutex::_allow_vm_block_flag);    // allow_vm_block
   903     }
   904     guarantee(result != NULL, "shouldn't return NULL");
   905     assert(!result->is_locked(), "shouldn't be locked");
   906     // release lock().
   907   }
   908   return result;
   909 }
   911 void MonitorSupply::release(Monitor* instance) {
   912   assert(instance != NULL, "shouldn't release NULL");
   913   assert(!instance->is_locked(), "shouldn't be locked");
   914   {
   915     MutexLockerEx ml(lock());
   916     freelist()->push(instance);
   917     // release lock().
   918   }
   919 }

mercurial