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

Tue, 23 Nov 2010 13:22:55 -0800

author
stefank
date
Tue, 23 Nov 2010 13:22:55 -0800
changeset 2314
f95d63e2154a
parent 1907
c18cbe5936b8
child 3294
bca17e38de00
permissions
-rw-r--r--

6989984: Use standard include model for Hospot
Summary: Replaced MakeDeps and the includeDB files with more standardized solutions.
Reviewed-by: coleenp, kvn, kamg

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

mercurial