src/hotspot/share/gc/g1/g1ConcurrentRefineThread.cpp
changeset 47789 a77a7d3bc4f6
parent 47647 64dba69fc528
child 48103 26dbe08d1c17
equal deleted inserted replaced
47786:97dde3171e7e 47789:a77a7d3bc4f6
       
     1 /*
       
     2  * Copyright (c) 2001, 2017, 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/g1ConcurrentRefine.hpp"
       
    27 #include "gc/g1/g1ConcurrentRefineThread.hpp"
       
    28 #include "gc/g1/g1CollectedHeap.inline.hpp"
       
    29 #include "gc/g1/g1RemSet.hpp"
       
    30 #include "gc/shared/suspendibleThreadSet.hpp"
       
    31 #include "logging/log.hpp"
       
    32 #include "memory/resourceArea.hpp"
       
    33 #include "runtime/handles.inline.hpp"
       
    34 #include "runtime/mutexLocker.hpp"
       
    35 
       
    36 G1ConcurrentRefineThread::G1ConcurrentRefineThread(G1ConcurrentRefine* cr,
       
    37                                                    G1ConcurrentRefineThread *next,
       
    38                                                    uint worker_id_offset,
       
    39                                                    uint worker_id,
       
    40                                                    size_t activate,
       
    41                                                    size_t deactivate) :
       
    42   ConcurrentGCThread(),
       
    43   _worker_id_offset(worker_id_offset),
       
    44   _worker_id(worker_id),
       
    45   _active(false),
       
    46   _next(next),
       
    47   _monitor(NULL),
       
    48   _cr(cr),
       
    49   _vtime_accum(0.0),
       
    50   _activation_threshold(activate),
       
    51   _deactivation_threshold(deactivate)
       
    52 {
       
    53 
       
    54   // Each thread has its own monitor. The i-th thread is responsible for signaling
       
    55   // to thread i+1 if the number of buffers in the queue exceeds a threshold for this
       
    56   // thread. Monitors are also used to wake up the threads during termination.
       
    57   // The 0th (primary) worker is notified by mutator threads and has a special monitor.
       
    58   if (!is_primary()) {
       
    59     _monitor = new Monitor(Mutex::nonleaf, "Refinement monitor", true,
       
    60                            Monitor::_safepoint_check_never);
       
    61   } else {
       
    62     _monitor = DirtyCardQ_CBL_mon;
       
    63   }
       
    64 
       
    65   // set name
       
    66   set_name("G1 Refine#%d", worker_id);
       
    67   create_and_start();
       
    68 }
       
    69 
       
    70 void G1ConcurrentRefineThread::update_thresholds(size_t activate,
       
    71                                                  size_t deactivate) {
       
    72   assert(deactivate < activate, "precondition");
       
    73   _activation_threshold = activate;
       
    74   _deactivation_threshold = deactivate;
       
    75 }
       
    76 
       
    77 void G1ConcurrentRefineThread::wait_for_completed_buffers() {
       
    78   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
       
    79   while (!should_terminate() && !is_active()) {
       
    80     _monitor->wait(Mutex::_no_safepoint_check_flag);
       
    81   }
       
    82 }
       
    83 
       
    84 bool G1ConcurrentRefineThread::is_active() {
       
    85   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
       
    86   return is_primary() ? dcqs.process_completed_buffers() : _active;
       
    87 }
       
    88 
       
    89 void G1ConcurrentRefineThread::activate() {
       
    90   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
       
    91   if (!is_primary()) {
       
    92     set_active(true);
       
    93   } else {
       
    94     DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
       
    95     dcqs.set_process_completed(true);
       
    96   }
       
    97   _monitor->notify();
       
    98 }
       
    99 
       
   100 void G1ConcurrentRefineThread::deactivate() {
       
   101   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
       
   102   if (!is_primary()) {
       
   103     set_active(false);
       
   104   } else {
       
   105     DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
       
   106     dcqs.set_process_completed(false);
       
   107   }
       
   108 }
       
   109 
       
   110 void G1ConcurrentRefineThread::run_service() {
       
   111   _vtime_start = os::elapsedVTime();
       
   112 
       
   113   while (!should_terminate()) {
       
   114     // Wait for work
       
   115     wait_for_completed_buffers();
       
   116     if (should_terminate()) {
       
   117       break;
       
   118     }
       
   119 
       
   120     size_t buffers_processed = 0;
       
   121     DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
       
   122     log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT,
       
   123                           _worker_id, _activation_threshold, dcqs.completed_buffers_num());
       
   124 
       
   125     {
       
   126       SuspendibleThreadSetJoiner sts_join;
       
   127 
       
   128       while (!should_terminate()) {
       
   129         if (sts_join.should_yield()) {
       
   130           sts_join.yield();
       
   131           continue;             // Re-check for termination after yield delay.
       
   132         }
       
   133 
       
   134         size_t curr_buffer_num = dcqs.completed_buffers_num();
       
   135         // If the number of the buffers falls down into the yellow zone,
       
   136         // that means that the transition period after the evacuation pause has ended.
       
   137         if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cr()->yellow_zone()) {
       
   138           dcqs.set_completed_queue_padding(0);
       
   139         }
       
   140 
       
   141         // Check if we need to activate the next thread.
       
   142         if ((_next != NULL) &&
       
   143             !_next->is_active() &&
       
   144             (curr_buffer_num > _next->_activation_threshold)) {
       
   145           _next->activate();
       
   146         }
       
   147 
       
   148         // Process the next buffer, if there are enough left.
       
   149         if (!dcqs.refine_completed_buffer_concurrently(_worker_id + _worker_id_offset, _deactivation_threshold)) {
       
   150           break; // Deactivate, number of buffers fell below threshold.
       
   151         }
       
   152         ++buffers_processed;
       
   153       }
       
   154     }
       
   155 
       
   156     deactivate();
       
   157     log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT
       
   158                           ", current: " SIZE_FORMAT ", processed: " SIZE_FORMAT,
       
   159                           _worker_id, _deactivation_threshold,
       
   160                           dcqs.completed_buffers_num(),
       
   161                           buffers_processed);
       
   162 
       
   163     if (os::supports_vtime()) {
       
   164       _vtime_accum = (os::elapsedVTime() - _vtime_start);
       
   165     } else {
       
   166       _vtime_accum = 0.0;
       
   167     }
       
   168   }
       
   169 
       
   170   log_debug(gc, refine)("Stopping %d", _worker_id);
       
   171 }
       
   172 
       
   173 void G1ConcurrentRefineThread::stop_service() {
       
   174   MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag);
       
   175   _monitor->notify();
       
   176 }