1 /* 2 * Copyright (c) 2013, 2021, Red Hat, Inc. All rights reserved. 3 * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. 4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5 * 6 * This code is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 only, as 8 * published by the Free Software Foundation. 9 * 10 * This code is distributed in the hope that it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13 * version 2 for more details (a copy is included in the LICENSE file that 14 * accompanied this code). 15 * 16 * You should have received a copy of the GNU General Public License version 17 * 2 along with this work; if not, write to the Free Software Foundation, 18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 19 * 20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 21 * or visit www.oracle.com if you need additional information or have any 22 * questions. 23 * 24 */ 25 26 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALCONTROLTHREAD_HPP 27 #define SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALCONTROLTHREAD_HPP 28 29 #include "gc/shared/gcCause.hpp" 30 #include "gc/shenandoah/shenandoahController.hpp" 31 #include "gc/shenandoah/shenandoahGC.hpp" 32 #include "gc/shenandoah/shenandoahSharedVariables.hpp" 33 #include "runtime/mutexLocker.hpp" 34 35 class ShenandoahOldGeneration; 36 class ShenandoahGeneration; 37 class ShenandoahGenerationalHeap; 38 class ShenandoahHeap; 39 40 class ShenandoahGenerationalControlThread: public ShenandoahController { 41 friend class VMStructs; 42 43 public: 44 typedef enum { 45 none, 46 concurrent_normal, 47 stw_degenerated, 48 stw_full, 49 bootstrapping_old, 50 servicing_old, 51 stopped 52 } GCMode; 53 54 class ShenandoahGCRequest { 55 public: 56 ShenandoahGCRequest() : generation(nullptr), cause(GCCause::_no_gc) {} 57 ShenandoahGeneration* generation; 58 GCCause::Cause cause; 59 }; 60 61 private: 62 // This lock is used to coordinate setting the _requested_gc_cause, _requested generation 63 // and _gc_mode. It is important that these be changed together and have a consistent view. 64 Monitor _control_lock; 65 66 // Represents a normal (non cancellation) gc request. This can be set by mutators (System.gc, 67 // whitebox gc, etc.) or by the regulator thread when the heuristics want to start a cycle. 68 GCCause::Cause _requested_gc_cause; 69 70 // This is the generation the request should operate on. 71 ShenandoahGeneration* _requested_generation; 72 73 // The mode is read frequently by requesting threads and only ever written by the control thread. 74 // This may be read without taking the _control_lock, but should be read again under the lock 75 // before making any state changes (double-checked locking idiom). 76 volatile GCMode _gc_mode; 77 78 // Only the control thread knows the correct degeneration point. This is used to have the 79 // control thread resume a STW cycle from the point where the concurrent cycle was cancelled. 80 ShenandoahGC::ShenandoahDegenPoint _degen_point; 81 82 // A reference to the heap 83 ShenandoahGenerationalHeap* _heap; 84 85 // This is used to keep track of whether to age objects during the current cycle. 86 uint _age_period; 87 88 // This is true when the old generation cycle is in an interruptible phase (i.e., marking or 89 // preparing for mark). 90 ShenandoahSharedFlag _allow_old_preemption; 91 92 public: 93 ShenandoahGenerationalControlThread(); 94 95 void run_service() override; 96 void stop_service() override; 97 98 void request_gc(GCCause::Cause cause) override; 99 100 // Return true if the request to start a concurrent GC for the given generation succeeded. 101 bool request_concurrent_gc(ShenandoahGeneration* generation); 102 103 // Returns the current state of the control thread 104 GCMode gc_mode() const { 105 return _gc_mode; 106 } 107 private: 108 // Returns true if the cycle has been cancelled or degenerated. 109 bool check_cancellation_or_degen(ShenandoahGC::ShenandoahDegenPoint point); 110 111 // Executes one GC cycle 112 void run_gc_cycle(const ShenandoahGCRequest& request); 113 114 // Returns true if the old generation marking completed (i.e., final mark executed for old generation). 115 bool resume_concurrent_old_cycle(ShenandoahOldGeneration* generation, GCCause::Cause cause); 116 117 // Various service methods handle different gc cycle types 118 void service_concurrent_cycle(ShenandoahGeneration* generation, GCCause::Cause cause, bool reset_old_bitmap_specially); 119 void service_stw_full_cycle(GCCause::Cause cause); 120 void service_stw_degenerated_cycle(const ShenandoahGCRequest& request); 121 void service_concurrent_normal_cycle(const ShenandoahGCRequest& request); 122 void service_concurrent_old_cycle(const ShenandoahGCRequest& request); 123 124 void notify_gc_waiters(); 125 126 // Blocks until at least one global GC cycle is complete. 127 void handle_requested_gc(GCCause::Cause cause); 128 129 // Returns true if the old generation marking was interrupted to allow a young cycle. 130 bool preempt_old_marking(ShenandoahGeneration* generation); 131 132 // Flushes cycle timings to global timings and prints the phase timings for the last completed cycle. 133 void process_phase_timings() const; 134 135 // Set the gc mode and post a notification if it has changed. The overloaded variant should be used 136 // when the _control_lock is already held. 137 void set_gc_mode(GCMode new_mode); 138 void set_gc_mode(MonitorLocker& ml, GCMode new_mode); 139 140 // Return printable name for the given gc mode. 141 static const char* gc_mode_name(GCMode mode); 142 143 // Takes the request lock and updates the requested cause and generation, then notifies the control thread. 144 // The overloaded variant should be used when the _control_lock is already held. 145 void notify_control_thread(GCCause::Cause cause, ShenandoahGeneration* generation); 146 void notify_control_thread(MonitorLocker& ml, GCCause::Cause cause, ShenandoahGeneration* generation); 147 148 // Notifies the control thread, but does not update the requested cause or generation. 149 // The overloaded variant should be used when the _control_lock is already held. 150 void notify_cancellation(GCCause::Cause cause); 151 void notify_cancellation(MonitorLocker& ml, GCCause::Cause cause); 152 153 // Configure the heap to age objects and regions if the aging period has elapsed. 154 void maybe_set_aging_cycle(); 155 156 // Take the _control_lock and check for a request to run a gc cycle. If a request is found, 157 // the `prepare` methods are used to configure the heap and update heuristics accordingly. 158 void check_for_request(ShenandoahGCRequest& request); 159 160 GCMode prepare_for_allocation_failure_gc(ShenandoahGCRequest &request); 161 GCMode prepare_for_explicit_gc(ShenandoahGCRequest &request) const; 162 GCMode prepare_for_concurrent_gc(const ShenandoahGCRequest &request) const; 163 }; 164 165 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHGENERATIONALCONTROLTHREAD_HPP