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

Mon, 11 May 2009 16:30:56 -0700

author
iveresov
date
Mon, 11 May 2009 16:30:56 -0700
changeset 1229
315a5d70b295
parent 1186
20c6f43950b5
child 1230
215f81b4d9b3
permissions
-rw-r--r--

6484957: G1: parallel concurrent refinement
6826318: G1: remove traversal-based refinement code
Summary: Removed traversal-based refinement code as it's no longer used. Made the concurrent refinement (queue-based) parallel.
Reviewed-by: tonyp

     1 /*
     2  * Copyright 2001-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/_concurrentG1RefineThread.cpp.incl"
    28 // ======= Concurrent Mark Thread ========
    30 // The CM thread is created when the G1 garbage collector is used
    32 ConcurrentG1RefineThread::
    33 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next, int worker_id) :
    34   ConcurrentGCThread(),
    35   _worker_id(worker_id),
    36   _active(false),
    37   _next(next),
    38   _cg1r(cg1r),
    39   _vtime_accum(0.0),
    40   _co_tracker(G1CRGroup),
    41   _interval_ms(5.0)
    42 {
    43   create_and_start();
    44 }
    46 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
    47   G1CollectedHeap* g1h = G1CollectedHeap::heap();
    48   G1CollectorPolicy* g1p = g1h->g1_policy();
    49   if (g1p->adaptive_young_list_length()) {
    50     int regions_visited = 0;
    52     g1h->young_list_rs_length_sampling_init();
    53     while (g1h->young_list_rs_length_sampling_more()) {
    54       g1h->young_list_rs_length_sampling_next();
    55       ++regions_visited;
    57       // we try to yield every time we visit 10 regions
    58       if (regions_visited == 10) {
    59         if (_sts.should_yield()) {
    60           _sts.yield("G1 refine");
    61           // we just abandon the iteration
    62           break;
    63         }
    64         regions_visited = 0;
    65       }
    66     }
    68     g1p->check_prediction_validity();
    69   }
    70 }
    72 void ConcurrentG1RefineThread::run() {
    73   initialize_in_thread();
    74   _vtime_start = os::elapsedVTime();
    75   wait_for_universe_init();
    77   _co_tracker.enable();
    78   _co_tracker.start();
    80   while (!_should_terminate) {
    81     DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
    82     // Wait for completed log buffers to exist.
    83     {
    84       MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
    85       while (((_worker_id == 0 && !dcqs.process_completed_buffers()) ||
    86               (_worker_id > 0 && !is_active())) &&
    87              !_should_terminate) {
    88          DirtyCardQ_CBL_mon->wait(Mutex::_no_safepoint_check_flag);
    89       }
    90     }
    92     if (_should_terminate) {
    93       return;
    94     }
    96     // Now we take them off (this doesn't hold locks while it applies
    97     // closures.)  (If we did a full collection, then we'll do a full
    98     // traversal.
    99     _sts.join();
   100     int n_logs = 0;
   101     int lower_limit = 0;
   102     double start_vtime_sec; // only used when G1SmoothConcRefine is on
   103     int prev_buffer_num; // only used when G1SmoothConcRefine is on
   104     // This thread activation threshold
   105     int threshold = DCQBarrierProcessCompletedThreshold * _worker_id;
   106     // Next thread activation threshold
   107     int next_threshold = threshold + DCQBarrierProcessCompletedThreshold;
   108     int deactivation_threshold = MAX2<int>(threshold - DCQBarrierProcessCompletedThreshold / 2, 0);
   110     if (G1SmoothConcRefine) {
   111       lower_limit = 0;
   112       start_vtime_sec = os::elapsedVTime();
   113       prev_buffer_num = (int) dcqs.completed_buffers_num();
   114     } else {
   115       lower_limit = DCQBarrierProcessCompletedThreshold / 4; // For now.
   116     }
   117     while (dcqs.apply_closure_to_completed_buffer(_worker_id, lower_limit)) {
   118       double end_vtime_sec;
   119       double elapsed_vtime_sec;
   120       int elapsed_vtime_ms;
   121       int curr_buffer_num = (int) dcqs.completed_buffers_num();
   123       if (G1SmoothConcRefine) {
   124         end_vtime_sec = os::elapsedVTime();
   125         elapsed_vtime_sec = end_vtime_sec - start_vtime_sec;
   126         elapsed_vtime_ms = (int) (elapsed_vtime_sec * 1000.0);
   128         if (curr_buffer_num > prev_buffer_num ||
   129             curr_buffer_num > next_threshold) {
   130           decreaseInterval(elapsed_vtime_ms);
   131         } else if (curr_buffer_num < prev_buffer_num) {
   132           increaseInterval(elapsed_vtime_ms);
   133         }
   134       }
   135       if (_worker_id == 0) {
   136         sample_young_list_rs_lengths();
   137       } else if (curr_buffer_num < deactivation_threshold) {
   138         // If the number of the buffer has fallen below our threshold
   139         // we should deactivate. The predecessor will reactivate this
   140         // thread should the number of the buffers cross the threshold again.
   141         MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
   142         deactivate();
   143         if (G1TraceConcurrentRefinement) {
   144           gclog_or_tty->print_cr("G1-Refine-deactivated worker %d", _worker_id);
   145         }
   146         break;
   147       }
   148       _co_tracker.update(false);
   150       // Check if we need to activate the next thread.
   151       if (curr_buffer_num > next_threshold && _next != NULL && !_next->is_active()) {
   152         MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
   153         _next->activate();
   154         DirtyCardQ_CBL_mon->notify_all();
   155         if (G1TraceConcurrentRefinement) {
   156           gclog_or_tty->print_cr("G1-Refine-activated worker %d", _next->_worker_id);
   157         }
   158       }
   160       if (G1SmoothConcRefine) {
   161         prev_buffer_num = curr_buffer_num;
   162         _sts.leave();
   163         os::sleep(Thread::current(), (jlong) _interval_ms, false);
   164         _sts.join();
   165         start_vtime_sec = os::elapsedVTime();
   166       }
   167       n_logs++;
   168     }
   169     _co_tracker.update(false);
   170     _sts.leave();
   172     if (os::supports_vtime()) {
   173       _vtime_accum = (os::elapsedVTime() - _vtime_start);
   174     } else {
   175       _vtime_accum = 0.0;
   176     }
   177   }
   178   _sts.join();
   179   _co_tracker.update(true);
   180   _sts.leave();
   181   assert(_should_terminate, "just checking");
   183   terminate();
   184 }
   187 void ConcurrentG1RefineThread::yield() {
   188   if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-yield");
   189   _sts.yield("G1 refine");
   190   if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-yield-end");
   191 }
   193 void ConcurrentG1RefineThread::stop() {
   194   // it is ok to take late safepoints here, if needed
   195   {
   196     MutexLockerEx mu(Terminator_lock);
   197     _should_terminate = true;
   198   }
   200   {
   201     MutexLockerEx x(DirtyCardQ_CBL_mon, Mutex::_no_safepoint_check_flag);
   202     DirtyCardQ_CBL_mon->notify_all();
   203   }
   205   {
   206     MutexLockerEx mu(Terminator_lock);
   207     while (!_has_terminated) {
   208       Terminator_lock->wait();
   209     }
   210   }
   211   if (G1TraceConcurrentRefinement) gclog_or_tty->print_cr("G1-Refine-stop");
   212 }
   214 void ConcurrentG1RefineThread::print() {
   215   gclog_or_tty->print("\"Concurrent G1 Refinement Thread\" ");
   216   Thread::print();
   217   gclog_or_tty->cr();
   218 }

mercurial