src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp

Thu, 15 Apr 2010 18:45:30 -0400

author
tonyp
date
Thu, 15 Apr 2010 18:45:30 -0400
changeset 1825
f9ec1e4bbb44
parent 1717
b81f3572f355
child 1829
1316cec51b4d
permissions
-rw-r--r--

6939027: G1: assertion failure during the concurrent phase of cleanup
Summary: The outgoing region map is not maintained properly and it's causing an assert failure. Given that we don't actually use it, I'm removing it. I'm piggy-backing a small change on this which removes a message that it's printed before a Full GC when DisableExplicitGC is set.
Reviewed-by: apetrusenko, ysr

     1 /*
     2  * Copyright 2001-2009 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/_concurrentG1RefineThread.cpp.incl"
    28 ConcurrentG1RefineThread::
    29 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
    30                          int worker_id_offset, int worker_id) :
    31   ConcurrentGCThread(),
    32   _worker_id_offset(worker_id_offset),
    33   _worker_id(worker_id),
    34   _active(false),
    35   _next(next),
    36   _monitor(NULL),
    37   _cg1r(cg1r),
    38   _vtime_accum(0.0)
    39 {
    41   // Each thread has its own monitor. The i-th thread is responsible for signalling
    42   // to thread i+1 if the number of buffers in the queue exceeds a threashold for this
    43   // thread. Monitors are also used to wake up the threads during termination.
    44   // The 0th worker in notified by mutator threads and has a special monitor.
    45   // The last worker is used for young gen rset size sampling.
    46   if (worker_id > 0) {
    47     _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true);
    48   } else {
    49     _monitor = DirtyCardQ_CBL_mon;
    50   }
    51   initialize();
    52   create_and_start();
    53 }
    55 void ConcurrentG1RefineThread::initialize() {
    56   if (_worker_id < cg1r()->worker_thread_num()) {
    57     // Current thread activation threshold
    58     _threshold = MIN2<int>(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(),
    59                            cg1r()->yellow_zone());
    60     // A thread deactivates once the number of buffer reached a deactivation threshold
    61     _deactivation_threshold = MAX2<int>(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone());
    62   } else {
    63     set_active(true);
    64   }
    65 }
    67 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
    68   G1CollectedHeap* g1h = G1CollectedHeap::heap();
    69   G1CollectorPolicy* g1p = g1h->g1_policy();
    70   if (g1p->adaptive_young_list_length()) {
    71     int regions_visited = 0;
    72     g1h->young_list_rs_length_sampling_init();
    73     while (g1h->young_list_rs_length_sampling_more()) {
    74       g1h->young_list_rs_length_sampling_next();
    75       ++regions_visited;
    77       // we try to yield every time we visit 10 regions
    78       if (regions_visited == 10) {
    79         if (_sts.should_yield()) {
    80           _sts.yield("G1 refine");
    81           // we just abandon the iteration
    82           break;
    83         }
    84         regions_visited = 0;
    85       }
    86     }
    88     g1p->check_prediction_validity();
    89   }
    90 }
    92 void ConcurrentG1RefineThread::run_young_rs_sampling() {
    93   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
    94   _vtime_start = os::elapsedVTime();
    95   while(!_should_terminate) {
    96     _sts.join();
    97     sample_young_list_rs_lengths();
    98     _sts.leave();
   100     if (os::supports_vtime()) {
   101       _vtime_accum = (os::elapsedVTime() - _vtime_start);
   102     } else {
   103       _vtime_accum = 0.0;
   104     }
   106     MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
   107     if (_should_terminate) {
   108       break;
   109     }
   110     _monitor->wait(Mutex::_no_safepoint_check_flag, G1ConcRefinementServiceIntervalMillis);
   111   }
   112 }
   114 void ConcurrentG1RefineThread::wait_for_completed_buffers() {
   115   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   116   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
   117   while (!_should_terminate && !is_active()) {
   118     _monitor->wait(Mutex::_no_safepoint_check_flag);
   119   }
   120 }
   122 bool ConcurrentG1RefineThread::is_active() {
   123   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   124   return _worker_id > 0 ? _active : dcqs.process_completed_buffers();
   125 }
   127 void ConcurrentG1RefineThread::activate() {
   128   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
   129   if (_worker_id > 0) {
   130     if (G1TraceConcRefinement) {
   131       DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   132       gclog_or_tty->print_cr("G1-Refine-activated worker %d, on threshold %d, current %d",
   133                              _worker_id, _threshold, (int)dcqs.completed_buffers_num());
   134     }
   135     set_active(true);
   136   } else {
   137     DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   138     dcqs.set_process_completed(true);
   139   }
   140   _monitor->notify();
   141 }
   143 void ConcurrentG1RefineThread::deactivate() {
   144   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
   145   if (_worker_id > 0) {
   146     if (G1TraceConcRefinement) {
   147       DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   148       gclog_or_tty->print_cr("G1-Refine-deactivated worker %d, off threshold %d, current %d",
   149                              _worker_id, _deactivation_threshold, (int)dcqs.completed_buffers_num());
   150     }
   151     set_active(false);
   152   } else {
   153     DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   154     dcqs.set_process_completed(false);
   155   }
   156 }
   158 void ConcurrentG1RefineThread::run() {
   159   initialize_in_thread();
   160   wait_for_universe_init();
   162   if (_worker_id >= cg1r()->worker_thread_num()) {
   163     run_young_rs_sampling();
   164     terminate();
   165   }
   167   _vtime_start = os::elapsedVTime();
   168   while (!_should_terminate) {
   169     DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   171     // Wait for work
   172     wait_for_completed_buffers();
   174     if (_should_terminate) {
   175       break;
   176     }
   178     _sts.join();
   180     do {
   181       int curr_buffer_num = (int)dcqs.completed_buffers_num();
   182       // If the number of the buffers falls down into the yellow zone,
   183       // that means that the transition period after the evacuation pause has ended.
   184       if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
   185         dcqs.set_completed_queue_padding(0);
   186       }
   188       if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
   189         // If the number of the buffer has fallen below our threshold
   190         // we should deactivate. The predecessor will reactivate this
   191         // thread should the number of the buffers cross the threshold again.
   192         deactivate();
   193         break;
   194       }
   196       // Check if we need to activate the next thread.
   197       if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
   198         _next->activate();
   199       }
   200     } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone()));
   202     // We can exit the loop above while being active if there was a yield request.
   203     if (is_active()) {
   204       deactivate();
   205     }
   207     _sts.leave();
   209     if (os::supports_vtime()) {
   210       _vtime_accum = (os::elapsedVTime() - _vtime_start);
   211     } else {
   212       _vtime_accum = 0.0;
   213     }
   214   }
   215   assert(_should_terminate, "just checking");
   216   terminate();
   217 }
   220 void ConcurrentG1RefineThread::yield() {
   221   if (G1TraceConcRefinement) {
   222     gclog_or_tty->print_cr("G1-Refine-yield");
   223   }
   224   _sts.yield("G1 refine");
   225   if (G1TraceConcRefinement) {
   226     gclog_or_tty->print_cr("G1-Refine-yield-end");
   227   }
   228 }
   230 void ConcurrentG1RefineThread::stop() {
   231   // it is ok to take late safepoints here, if needed
   232   {
   233     MutexLockerEx mu(Terminator_lock);
   234     _should_terminate = true;
   235   }
   237   {
   238     MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
   239     _monitor->notify();
   240   }
   242   {
   243     MutexLockerEx mu(Terminator_lock);
   244     while (!_has_terminated) {
   245       Terminator_lock->wait();
   246     }
   247   }
   248   if (G1TraceConcRefinement) {
   249     gclog_or_tty->print_cr("G1-Refine-stop");
   250   }
   251 }
   253 void ConcurrentG1RefineThread::print() const {
   254   print_on(tty);
   255 }
   257 void ConcurrentG1RefineThread::print_on(outputStream* st) const {
   258   st->print("\"G1 Concurrent Refinement Thread#%d\" ", _worker_id);
   259   Thread::print_on(st);
   260   st->cr();
   261 }

mercurial