Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp
38920 views
1
/*
2
* Copyright (c) 2001, 2013, 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_implementation/g1/concurrentMarkThread.inline.hpp"
27
#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
28
#include "gc_implementation/g1/g1CollectorPolicy.hpp"
29
#include "gc_implementation/g1/g1Log.hpp"
30
#include "gc_implementation/g1/g1MMUTracker.hpp"
31
#include "gc_implementation/g1/vm_operations_g1.hpp"
32
#include "gc_implementation/shared/gcTrace.hpp"
33
#include "memory/resourceArea.hpp"
34
#include "runtime/vmThread.hpp"
35
36
// ======= Concurrent Mark Thread ========
37
38
// The CM thread is created when the G1 garbage collector is used
39
40
SurrogateLockerThread*
41
ConcurrentMarkThread::_slt = NULL;
42
43
ConcurrentMarkThread::ConcurrentMarkThread(ConcurrentMark* cm) :
44
ConcurrentGCThread(),
45
_cm(cm),
46
_state(Idle),
47
_vtime_accum(0.0),
48
_vtime_mark_accum(0.0) {
49
create_and_start();
50
}
51
52
class CMCheckpointRootsFinalClosure: public VoidClosure {
53
54
ConcurrentMark* _cm;
55
public:
56
57
CMCheckpointRootsFinalClosure(ConcurrentMark* cm) :
58
_cm(cm) {}
59
60
void do_void(){
61
_cm->checkpointRootsFinal(false); // !clear_all_soft_refs
62
}
63
};
64
65
class CMCleanUp: public VoidClosure {
66
ConcurrentMark* _cm;
67
public:
68
69
CMCleanUp(ConcurrentMark* cm) :
70
_cm(cm) {}
71
72
void do_void(){
73
_cm->cleanup();
74
}
75
};
76
77
78
79
void ConcurrentMarkThread::run() {
80
initialize_in_thread();
81
_vtime_start = os::elapsedVTime();
82
wait_for_universe_init();
83
84
G1CollectedHeap* g1h = G1CollectedHeap::heap();
85
G1CollectorPolicy* g1_policy = g1h->g1_policy();
86
G1MMUTracker *mmu_tracker = g1_policy->mmu_tracker();
87
Thread *current_thread = Thread::current();
88
89
while (!_should_terminate) {
90
// wait until started is set.
91
sleepBeforeNextCycle();
92
if (_should_terminate) {
93
break;
94
}
95
96
{
97
ResourceMark rm;
98
HandleMark hm;
99
double cycle_start = os::elapsedVTime();
100
101
// We have to ensure that we finish scanning the root regions
102
// before the next GC takes place. To ensure this we have to
103
// make sure that we do not join the STS until the root regions
104
// have been scanned. If we did then it's possible that a
105
// subsequent GC could block us from joining the STS and proceed
106
// without the root regions have been scanned which would be a
107
// correctness issue.
108
109
double scan_start = os::elapsedTime();
110
if (!cm()->has_aborted()) {
111
if (G1Log::fine()) {
112
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
113
gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]");
114
}
115
116
_cm->scanRootRegions();
117
118
double scan_end = os::elapsedTime();
119
if (G1Log::fine()) {
120
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
121
gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]",
122
scan_end - scan_start);
123
}
124
}
125
126
double mark_start_sec = os::elapsedTime();
127
if (G1Log::fine()) {
128
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
129
gclog_or_tty->print_cr("[GC concurrent-mark-start]");
130
}
131
132
int iter = 0;
133
do {
134
iter++;
135
if (!cm()->has_aborted()) {
136
_cm->markFromRoots();
137
}
138
139
double mark_end_time = os::elapsedVTime();
140
double mark_end_sec = os::elapsedTime();
141
_vtime_mark_accum += (mark_end_time - cycle_start);
142
if (!cm()->has_aborted()) {
143
if (g1_policy->adaptive_young_list_length()) {
144
double now = os::elapsedTime();
145
double remark_prediction_ms = g1_policy->predict_remark_time_ms();
146
jlong sleep_time_ms = mmu_tracker->when_ms(now, remark_prediction_ms);
147
os::sleep(current_thread, sleep_time_ms, false);
148
}
149
150
if (G1Log::fine()) {
151
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
152
gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf secs]",
153
mark_end_sec - mark_start_sec);
154
}
155
156
CMCheckpointRootsFinalClosure final_cl(_cm);
157
VM_CGC_Operation op(&final_cl, "GC remark", true /* needs_pll */);
158
VMThread::execute(&op);
159
}
160
if (cm()->restart_for_overflow()) {
161
if (G1TraceMarkStackOverflow) {
162
gclog_or_tty->print_cr("Restarting conc marking because of MS overflow "
163
"in remark (restart #%d).", iter);
164
}
165
if (G1Log::fine()) {
166
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
167
gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]");
168
}
169
}
170
} while (cm()->restart_for_overflow());
171
172
double end_time = os::elapsedVTime();
173
// Update the total virtual time before doing this, since it will try
174
// to measure it to get the vtime for this marking. We purposely
175
// neglect the presumably-short "completeCleanup" phase here.
176
_vtime_accum = (end_time - _vtime_start);
177
178
if (!cm()->has_aborted()) {
179
if (g1_policy->adaptive_young_list_length()) {
180
double now = os::elapsedTime();
181
double cleanup_prediction_ms = g1_policy->predict_cleanup_time_ms();
182
jlong sleep_time_ms = mmu_tracker->when_ms(now, cleanup_prediction_ms);
183
os::sleep(current_thread, sleep_time_ms, false);
184
}
185
186
CMCleanUp cl_cl(_cm);
187
VM_CGC_Operation op(&cl_cl, "GC cleanup", false /* needs_pll */);
188
VMThread::execute(&op);
189
} else {
190
// We don't want to update the marking status if a GC pause
191
// is already underway.
192
SuspendibleThreadSetJoiner sts;
193
g1h->set_marking_complete();
194
}
195
196
// Check if cleanup set the free_regions_coming flag. If it
197
// hasn't, we can just skip the next step.
198
if (g1h->free_regions_coming()) {
199
// The following will finish freeing up any regions that we
200
// found to be empty during cleanup. We'll do this part
201
// without joining the suspendible set. If an evacuation pause
202
// takes place, then we would carry on freeing regions in
203
// case they are needed by the pause. If a Full GC takes
204
// place, it would wait for us to process the regions
205
// reclaimed by cleanup.
206
207
double cleanup_start_sec = os::elapsedTime();
208
if (G1Log::fine()) {
209
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
210
gclog_or_tty->print_cr("[GC concurrent-cleanup-start]");
211
}
212
213
// Now do the concurrent cleanup operation.
214
_cm->completeCleanup();
215
216
// Notify anyone who's waiting that there are no more free
217
// regions coming. We have to do this before we join the STS
218
// (in fact, we should not attempt to join the STS in the
219
// interval between finishing the cleanup pause and clearing
220
// the free_regions_coming flag) otherwise we might deadlock:
221
// a GC worker could be blocked waiting for the notification
222
// whereas this thread will be blocked for the pause to finish
223
// while it's trying to join the STS, which is conditional on
224
// the GC workers finishing.
225
g1h->reset_free_regions_coming();
226
227
double cleanup_end_sec = os::elapsedTime();
228
if (G1Log::fine()) {
229
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
230
gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]",
231
cleanup_end_sec - cleanup_start_sec);
232
}
233
}
234
guarantee(cm()->cleanup_list_is_empty(),
235
"at this point there should be no regions on the cleanup list");
236
237
// There is a tricky race before recording that the concurrent
238
// cleanup has completed and a potential Full GC starting around
239
// the same time. We want to make sure that the Full GC calls
240
// abort() on concurrent mark after
241
// record_concurrent_mark_cleanup_completed(), since abort() is
242
// the method that will reset the concurrent mark state. If we
243
// end up calling record_concurrent_mark_cleanup_completed()
244
// after abort() then we might incorrectly undo some of the work
245
// abort() did. Checking the has_aborted() flag after joining
246
// the STS allows the correct ordering of the two methods. There
247
// are two scenarios:
248
//
249
// a) If we reach here before the Full GC, the fact that we have
250
// joined the STS means that the Full GC cannot start until we
251
// leave the STS, so record_concurrent_mark_cleanup_completed()
252
// will complete before abort() is called.
253
//
254
// b) If we reach here during the Full GC, we'll be held up from
255
// joining the STS until the Full GC is done, which means that
256
// abort() will have completed and has_aborted() will return
257
// true to prevent us from calling
258
// record_concurrent_mark_cleanup_completed() (and, in fact, it's
259
// not needed any more as the concurrent mark state has been
260
// already reset).
261
{
262
SuspendibleThreadSetJoiner sts;
263
if (!cm()->has_aborted()) {
264
g1_policy->record_concurrent_mark_cleanup_completed();
265
}
266
}
267
268
if (cm()->has_aborted()) {
269
if (G1Log::fine()) {
270
gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
271
gclog_or_tty->print_cr("[GC concurrent-mark-abort]");
272
}
273
}
274
275
// We now want to allow clearing of the marking bitmap to be
276
// suspended by a collection pause.
277
// We may have aborted just before the remark. Do not bother clearing the
278
// bitmap then, as it has been done during mark abort.
279
if (!cm()->has_aborted()) {
280
SuspendibleThreadSetJoiner sts;
281
_cm->clearNextBitmap();
282
} else {
283
assert(!G1VerifyBitmaps || _cm->nextMarkBitmapIsClear(), "Next mark bitmap must be clear");
284
}
285
}
286
287
// Update the number of full collections that have been
288
// completed. This will also notify the FullGCCount_lock in case a
289
// Java thread is waiting for a full GC to happen (e.g., it
290
// called System.gc() with +ExplicitGCInvokesConcurrent).
291
{
292
SuspendibleThreadSetJoiner sts;
293
g1h->increment_old_marking_cycles_completed(true /* concurrent */);
294
g1h->register_concurrent_cycle_end();
295
}
296
}
297
assert(_should_terminate, "just checking");
298
299
terminate();
300
}
301
302
void ConcurrentMarkThread::stop() {
303
{
304
MutexLockerEx ml(Terminator_lock);
305
_should_terminate = true;
306
}
307
308
{
309
MutexLockerEx ml(CGC_lock, Mutex::_no_safepoint_check_flag);
310
CGC_lock->notify_all();
311
}
312
313
{
314
MutexLockerEx ml(Terminator_lock);
315
while (!_has_terminated) {
316
Terminator_lock->wait();
317
}
318
}
319
}
320
321
void ConcurrentMarkThread::print() const {
322
print_on(tty);
323
}
324
325
void ConcurrentMarkThread::print_on(outputStream* st) const {
326
st->print("\"G1 Main Concurrent Mark GC Thread\" ");
327
Thread::print_on(st);
328
st->cr();
329
}
330
331
void ConcurrentMarkThread::sleepBeforeNextCycle() {
332
// We join here because we don't want to do the "shouldConcurrentMark()"
333
// below while the world is otherwise stopped.
334
assert(!in_progress(), "should have been cleared");
335
336
MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
337
while (!started() && !_should_terminate) {
338
CGC_lock->wait(Mutex::_no_safepoint_check_flag);
339
}
340
341
if (started()) {
342
set_in_progress();
343
}
344
}
345
346
// Note: As is the case with CMS - this method, although exported
347
// by the ConcurrentMarkThread, which is a non-JavaThread, can only
348
// be called by a JavaThread. Currently this is done at vm creation
349
// time (post-vm-init) by the main/Primordial (Java)Thread.
350
// XXX Consider changing this in the future to allow the CM thread
351
// itself to create this thread?
352
void ConcurrentMarkThread::makeSurrogateLockerThread(TRAPS) {
353
assert(UseG1GC, "SLT thread needed only for concurrent GC");
354
assert(THREAD->is_Java_thread(), "must be a Java thread");
355
assert(_slt == NULL, "SLT already created");
356
_slt = SurrogateLockerThread::make(THREAD);
357
}
358
359