1 /*
2 * Copyright (c) 2017, 2021, Red Hat, 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 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 #ifndef SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
26 #define SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
27
28 #include "gc/shared/gcCause.hpp"
29 #include "gc/shared/gcTraceTime.inline.hpp"
30 #include "gc/shared/gcVMOperations.hpp"
31 #include "gc/shared/isGCActiveMark.hpp"
32 #include "gc/shared/suspendibleThreadSet.hpp"
33 #include "gc/shared/workerThread.hpp"
34 #include "gc/shenandoah/shenandoahPhaseTimings.hpp"
35 #include "gc/shenandoah/shenandoahThreadLocalData.hpp"
36 #include "jfr/jfrEvents.hpp"
37 #include "memory/allocation.hpp"
38 #include "runtime/safepoint.hpp"
39 #include "runtime/vmThread.hpp"
40 #include "runtime/vmOperations.hpp"
41 #include "services/memoryService.hpp"
42
43 class GCTimer;
44
45 class ShenandoahGCSession : public StackObj {
46 private:
47 ShenandoahHeap* const _heap;
48 GCTimer* const _timer;
49 GCTracer* const _tracer;
50
51 TraceMemoryManagerStats _trace_cycle;
52 public:
53 ShenandoahGCSession(GCCause::Cause cause);
54 ~ShenandoahGCSession();
55 };
56
57 /*
58 * ShenandoahGCPhaseTiming tracks Shenandoah specific timing information
59 * of a GC phase
60 */
61 class ShenandoahTimingsTracker : public StackObj {
62 private:
63 static ShenandoahPhaseTimings::Phase _current_phase;
64
65 ShenandoahPhaseTimings* const _timings;
66 const ShenandoahPhaseTimings::Phase _phase;
67 const bool _should_aggregate;
68 ShenandoahPhaseTimings::Phase _parent_phase;
69 double _start;
70
71 public:
72 ShenandoahTimingsTracker(ShenandoahPhaseTimings::Phase phase, bool should_aggregate = false);
73 ~ShenandoahTimingsTracker();
74
75 static ShenandoahPhaseTimings::Phase current_phase() { return _current_phase; }
76
77 static bool is_current_phase_valid();
78 };
79
80 /*
81 * ShenandoahPausePhase tracks a STW pause and emits Shenandoah timing and
82 * a corresponding JFR event
83 */
84 class ShenandoahPausePhase : public ShenandoahTimingsTracker {
85 private:
86 GCTraceTimeWrapper<LogLevel::Info, LOG_TAGS(gc)> _tracer;
87 ConcurrentGCTimer* const _timer;
88
89 public:
90 ShenandoahPausePhase(const char* title, ShenandoahPhaseTimings::Phase phase, bool log_heap_usage = false);
91 ~ShenandoahPausePhase();
92 };
93
94 /*
95 * ShenandoahConcurrentPhase tracks a concurrent GC phase and emits Shenandoah timing and
96 * a corresponding JFR event
97 */
98 class ShenandoahConcurrentPhase : public ShenandoahTimingsTracker {
99 private:
100 GCTraceTimeWrapper<LogLevel::Info, LOG_TAGS(gc)> _tracer;
101 ConcurrentGCTimer* const _timer;
102
103 public:
104 ShenandoahConcurrentPhase(const char* title, ShenandoahPhaseTimings::Phase phase, bool log_heap_usage = false);
105 ~ShenandoahConcurrentPhase();
106 };
107
108 /*
109 * ShenandoahGCPhase tracks Shenandoah specific timing information
110 * and emits a corresponding JFR event of a GC phase
111 */
112 class ShenandoahGCPhase : public ShenandoahTimingsTracker {
113 private:
114 ConcurrentGCTimer* const _timer;
115
116 public:
117 ShenandoahGCPhase(ShenandoahPhaseTimings::Phase phase);
118 ~ShenandoahGCPhase();
119 };
120
121 class ShenandoahGCWorkerPhase : public StackObj {
122 private:
123 ShenandoahPhaseTimings* const _timings;
124 const ShenandoahPhaseTimings::Phase _phase;
125 public:
126 ShenandoahGCWorkerPhase(ShenandoahPhaseTimings::Phase phase);
127 ~ShenandoahGCWorkerPhase();
128 };
129
130 // Aggregates all the things that should happen before/after the pause.
131 class ShenandoahGCPauseMark : public StackObj {
132 private:
133 ShenandoahHeap* const _heap;
134 const GCIdMark _gc_id_mark;
135 const SvcGCMarker _svc_gc_mark;
136 const IsSTWGCActiveMark _is_gc_active_mark;
137 TraceMemoryManagerStats _trace_pause;
138
139 public:
140 ShenandoahGCPauseMark(uint gc_id, const char* notification_action, SvcGCMarker::reason_type type);
141 };
142
143 class ShenandoahSafepoint : public AllStatic {
144 public:
145 // Check if Shenandoah GC safepoint is in progress. This is nominally
146 // equivalent to calling SafepointSynchronize::is_at_safepoint(), but
147 // it also checks the Shenandoah specifics, when it can.
148 static inline bool is_at_shenandoah_safepoint() {
149 if (!SafepointSynchronize::is_at_safepoint()) return false;
150
151 Thread* const thr = Thread::current();
152 // Shenandoah GC specific safepoints are scheduled by control thread.
153 // So if we are enter here from control thread, then we are definitely not
154 // at Shenandoah safepoint, but at something else.
155 if (thr == ShenandoahHeap::heap()->control_thread()) return false;
156
157 // This is not VM thread, cannot see what VM thread is doing,
158 // so pretend this is a proper Shenandoah safepoint
159 if (!thr->is_VM_thread()) return true;
160
161 // Otherwise check we are at proper operation type
162 VM_Operation* vm_op = VMThread::vm_operation();
163 if (vm_op == nullptr) return false;
164
165 VM_Operation::VMOp_Type type = vm_op->type();
166 return type == VM_Operation::VMOp_ShenandoahInitMark ||
167 type == VM_Operation::VMOp_ShenandoahFinalMarkStartEvac ||
168 type == VM_Operation::VMOp_ShenandoahInitUpdateRefs ||
169 type == VM_Operation::VMOp_ShenandoahFinalUpdateRefs ||
170 type == VM_Operation::VMOp_ShenandoahFinalRoots ||
171 type == VM_Operation::VMOp_ShenandoahFullGC ||
172 type == VM_Operation::VMOp_ShenandoahDegeneratedGC;
173 }
174 };
175
176 class ShenandoahWorkerSession : public StackObj {
177 protected:
178 ShenandoahWorkerSession(uint worker_id);
179 public:
180 static inline uint worker_id() {
181 return WorkerThread::worker_id();
182 }
183 };
184
185 class ShenandoahConcurrentWorkerSession : public ShenandoahWorkerSession {
186 private:
187 EventGCPhaseConcurrent _event;
188
189 public:
190 ShenandoahConcurrentWorkerSession(uint worker_id) : ShenandoahWorkerSession(worker_id) { }
191 ~ShenandoahConcurrentWorkerSession();
192 };
193
194 class ShenandoahParallelWorkerSession : public ShenandoahWorkerSession {
195 private:
196 EventGCPhaseParallel _event;
197
198 public:
199 ShenandoahParallelWorkerSession(uint worker_id) : ShenandoahWorkerSession(worker_id) { }
200 ~ShenandoahParallelWorkerSession();
201 };
202
203 class ShenandoahSuspendibleThreadSetJoiner {
204 private:
205 SuspendibleThreadSetJoiner _joiner;
206 public:
207 ShenandoahSuspendibleThreadSetJoiner(bool active = true) : _joiner(active) {
208 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be joined before evac scope");
209 }
210 ~ShenandoahSuspendibleThreadSetJoiner() {
211 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be left after evac scope");
212 }
213 };
214
215 class ShenandoahSuspendibleThreadSetLeaver {
216 private:
217 SuspendibleThreadSetLeaver _leaver;
218 public:
219 ShenandoahSuspendibleThreadSetLeaver(bool active = true) : _leaver(active) {
220 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be left after evac scope");
221 }
222 ~ShenandoahSuspendibleThreadSetLeaver() {
223 assert(!ShenandoahThreadLocalData::is_evac_allowed(Thread::current()), "STS should be joined before evac scope");
224 }
225 };
226
227 #endif // SHARE_GC_SHENANDOAH_SHENANDOAHUTILS_HPP
--- EOF ---