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