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/concurrentMarkSweep/concurrentMarkSweepThread.cpp
38921 views
1
/*
2
* Copyright (c) 2001, 2014, 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 "classfile/systemDictionary.hpp"
27
#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.inline.hpp"
28
#include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
29
#include "memory/genCollectedHeap.hpp"
30
#include "oops/instanceRefKlass.hpp"
31
#include "oops/oop.inline.hpp"
32
#include "runtime/init.hpp"
33
#include "runtime/interfaceSupport.hpp"
34
#include "runtime/java.hpp"
35
#include "runtime/javaCalls.hpp"
36
#include "runtime/mutexLocker.hpp"
37
#include "runtime/os.hpp"
38
#include "runtime/vmThread.hpp"
39
40
// ======= Concurrent Mark Sweep Thread ========
41
42
// The CMS thread is created when Concurrent Mark Sweep is used in the
43
// older of two generations in a generational memory system.
44
45
ConcurrentMarkSweepThread*
46
ConcurrentMarkSweepThread::_cmst = NULL;
47
CMSCollector* ConcurrentMarkSweepThread::_collector = NULL;
48
bool ConcurrentMarkSweepThread::_should_terminate = false;
49
int ConcurrentMarkSweepThread::_CMS_flag = CMS_nil;
50
51
volatile jint ConcurrentMarkSweepThread::_pending_yields = 0;
52
volatile jint ConcurrentMarkSweepThread::_pending_decrements = 0;
53
54
volatile jint ConcurrentMarkSweepThread::_icms_disabled = 0;
55
volatile bool ConcurrentMarkSweepThread::_should_run = false;
56
// When icms is enabled, the icms thread is stopped until explicitly
57
// started.
58
volatile bool ConcurrentMarkSweepThread::_should_stop = true;
59
60
SurrogateLockerThread*
61
ConcurrentMarkSweepThread::_slt = NULL;
62
SurrogateLockerThread::SLT_msg_type
63
ConcurrentMarkSweepThread::_sltBuffer = SurrogateLockerThread::empty;
64
Monitor*
65
ConcurrentMarkSweepThread::_sltMonitor = NULL;
66
67
ConcurrentMarkSweepThread::ConcurrentMarkSweepThread(CMSCollector* collector)
68
: ConcurrentGCThread() {
69
assert(UseConcMarkSweepGC, "UseConcMarkSweepGC should be set");
70
assert(_cmst == NULL, "CMS thread already created");
71
_cmst = this;
72
assert(_collector == NULL, "Collector already set");
73
_collector = collector;
74
75
set_name("Concurrent Mark-Sweep GC Thread");
76
77
if (os::create_thread(this, os::cgc_thread)) {
78
// An old comment here said: "Priority should be just less
79
// than that of VMThread". Since the VMThread runs at
80
// NearMaxPriority, the old comment was inaccurate, but
81
// changing the default priority to NearMaxPriority-1
82
// could change current behavior, so the default of
83
// NearMaxPriority stays in place.
84
//
85
// Note that there's a possibility of the VMThread
86
// starving if UseCriticalCMSThreadPriority is on.
87
// That won't happen on Solaris for various reasons,
88
// but may well happen on non-Solaris platforms.
89
int native_prio;
90
if (UseCriticalCMSThreadPriority) {
91
native_prio = os::java_to_os_priority[CriticalPriority];
92
} else {
93
native_prio = os::java_to_os_priority[NearMaxPriority];
94
}
95
os::set_native_priority(this, native_prio);
96
97
if (!DisableStartThread) {
98
os::start_thread(this);
99
}
100
}
101
_sltMonitor = SLT_lock;
102
assert(!CMSIncrementalMode || icms_is_enabled(), "Error");
103
}
104
105
void ConcurrentMarkSweepThread::run() {
106
assert(this == cmst(), "just checking");
107
108
this->record_stack_base_and_size();
109
this->initialize_thread_local_storage();
110
this->set_active_handles(JNIHandleBlock::allocate_block());
111
// From this time Thread::current() should be working.
112
assert(this == Thread::current(), "just checking");
113
if (BindCMSThreadToCPU && !os::bind_to_processor(CPUForCMSThread)) {
114
warning("Couldn't bind CMS thread to processor " UINTX_FORMAT, CPUForCMSThread);
115
}
116
// Wait until Universe::is_fully_initialized()
117
{
118
CMSLoopCountWarn loopX("CMS::run", "waiting for "
119
"Universe::is_fully_initialized()", 2);
120
MutexLockerEx x(CGC_lock, true);
121
set_CMS_flag(CMS_cms_wants_token);
122
// Wait until Universe is initialized and all initialization is completed.
123
while (!is_init_completed() && !Universe::is_fully_initialized() &&
124
!_should_terminate) {
125
CGC_lock->wait(true, 200);
126
loopX.tick();
127
}
128
// Wait until the surrogate locker thread that will do
129
// pending list locking on our behalf has been created.
130
// We cannot start the SLT thread ourselves since we need
131
// to be a JavaThread to do so.
132
CMSLoopCountWarn loopY("CMS::run", "waiting for SLT installation", 2);
133
while (_slt == NULL && !_should_terminate) {
134
CGC_lock->wait(true, 200);
135
loopY.tick();
136
}
137
clear_CMS_flag(CMS_cms_wants_token);
138
}
139
140
while (!_should_terminate) {
141
sleepBeforeNextCycle();
142
if (_should_terminate) break;
143
GCCause::Cause cause = _collector->_full_gc_requested ?
144
_collector->_full_gc_cause : GCCause::_cms_concurrent_mark;
145
_collector->collect_in_background(false, cause);
146
}
147
assert(_should_terminate, "just checking");
148
// Check that the state of any protocol for synchronization
149
// between background (CMS) and foreground collector is "clean"
150
// (i.e. will not potentially block the foreground collector,
151
// requiring action by us).
152
verify_ok_to_terminate();
153
// Signal that it is terminated
154
{
155
MutexLockerEx mu(Terminator_lock,
156
Mutex::_no_safepoint_check_flag);
157
assert(_cmst == this, "Weird!");
158
_cmst = NULL;
159
Terminator_lock->notify();
160
}
161
162
// Thread destructor usually does this..
163
ThreadLocalStorage::set_thread(NULL);
164
}
165
166
#ifndef PRODUCT
167
void ConcurrentMarkSweepThread::verify_ok_to_terminate() const {
168
assert(!(CGC_lock->owned_by_self() || cms_thread_has_cms_token() ||
169
cms_thread_wants_cms_token()),
170
"Must renounce all worldly possessions and desires for nirvana");
171
_collector->verify_ok_to_terminate();
172
}
173
#endif
174
175
// create and start a new ConcurrentMarkSweep Thread for given CMS generation
176
ConcurrentMarkSweepThread* ConcurrentMarkSweepThread::start(CMSCollector* collector) {
177
if (!_should_terminate) {
178
assert(cmst() == NULL, "start() called twice?");
179
ConcurrentMarkSweepThread* th = new ConcurrentMarkSweepThread(collector);
180
assert(cmst() == th, "Where did the just-created CMS thread go?");
181
return th;
182
}
183
return NULL;
184
}
185
186
void ConcurrentMarkSweepThread::stop() {
187
if (CMSIncrementalMode) {
188
// Disable incremental mode and wake up the thread so it notices the change.
189
disable_icms();
190
start_icms();
191
}
192
// it is ok to take late safepoints here, if needed
193
{
194
MutexLockerEx x(Terminator_lock);
195
_should_terminate = true;
196
}
197
{ // Now post a notify on CGC_lock so as to nudge
198
// CMS thread(s) that might be slumbering in
199
// sleepBeforeNextCycle.
200
MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
201
CGC_lock->notify_all();
202
}
203
{ // Now wait until (all) CMS thread(s) have exited
204
MutexLockerEx x(Terminator_lock);
205
while(cmst() != NULL) {
206
Terminator_lock->wait();
207
}
208
}
209
}
210
211
void ConcurrentMarkSweepThread::threads_do(ThreadClosure* tc) {
212
assert(tc != NULL, "Null ThreadClosure");
213
if (_cmst != NULL) {
214
tc->do_thread(_cmst);
215
}
216
assert(Universe::is_fully_initialized(),
217
"Called too early, make sure heap is fully initialized");
218
if (_collector != NULL) {
219
AbstractWorkGang* gang = _collector->conc_workers();
220
if (gang != NULL) {
221
gang->threads_do(tc);
222
}
223
}
224
}
225
226
void ConcurrentMarkSweepThread::print_on(outputStream* st) const {
227
st->print("\"%s\" ", name());
228
Thread::print_on(st);
229
st->cr();
230
}
231
232
void ConcurrentMarkSweepThread::print_all_on(outputStream* st) {
233
if (_cmst != NULL) {
234
_cmst->print_on(st);
235
st->cr();
236
}
237
if (_collector != NULL) {
238
AbstractWorkGang* gang = _collector->conc_workers();
239
if (gang != NULL) {
240
gang->print_worker_threads_on(st);
241
}
242
}
243
}
244
245
void ConcurrentMarkSweepThread::synchronize(bool is_cms_thread) {
246
assert(UseConcMarkSweepGC, "just checking");
247
248
MutexLockerEx x(CGC_lock,
249
Mutex::_no_safepoint_check_flag);
250
if (!is_cms_thread) {
251
assert(Thread::current()->is_VM_thread(), "Not a VM thread");
252
CMSSynchronousYieldRequest yr;
253
while (CMS_flag_is_set(CMS_cms_has_token)) {
254
// indicate that we want to get the token
255
set_CMS_flag(CMS_vm_wants_token);
256
CGC_lock->wait(true);
257
}
258
// claim the token and proceed
259
clear_CMS_flag(CMS_vm_wants_token);
260
set_CMS_flag(CMS_vm_has_token);
261
} else {
262
assert(Thread::current()->is_ConcurrentGC_thread(),
263
"Not a CMS thread");
264
// The following barrier assumes there's only one CMS thread.
265
// This will need to be modified is there are more CMS threads than one.
266
while (CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token)) {
267
set_CMS_flag(CMS_cms_wants_token);
268
CGC_lock->wait(true);
269
}
270
// claim the token
271
clear_CMS_flag(CMS_cms_wants_token);
272
set_CMS_flag(CMS_cms_has_token);
273
}
274
}
275
276
void ConcurrentMarkSweepThread::desynchronize(bool is_cms_thread) {
277
assert(UseConcMarkSweepGC, "just checking");
278
279
MutexLockerEx x(CGC_lock,
280
Mutex::_no_safepoint_check_flag);
281
if (!is_cms_thread) {
282
assert(Thread::current()->is_VM_thread(), "Not a VM thread");
283
assert(CMS_flag_is_set(CMS_vm_has_token), "just checking");
284
clear_CMS_flag(CMS_vm_has_token);
285
if (CMS_flag_is_set(CMS_cms_wants_token)) {
286
// wake-up a waiting CMS thread
287
CGC_lock->notify();
288
}
289
assert(!CMS_flag_is_set(CMS_vm_has_token | CMS_vm_wants_token),
290
"Should have been cleared");
291
} else {
292
assert(Thread::current()->is_ConcurrentGC_thread(),
293
"Not a CMS thread");
294
assert(CMS_flag_is_set(CMS_cms_has_token), "just checking");
295
clear_CMS_flag(CMS_cms_has_token);
296
if (CMS_flag_is_set(CMS_vm_wants_token)) {
297
// wake-up a waiting VM thread
298
CGC_lock->notify();
299
}
300
assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
301
"Should have been cleared");
302
}
303
}
304
305
// Wait until any cms_lock event
306
void ConcurrentMarkSweepThread::wait_on_cms_lock(long t_millis) {
307
MutexLockerEx x(CGC_lock,
308
Mutex::_no_safepoint_check_flag);
309
if (_should_terminate || _collector->_full_gc_requested) {
310
return;
311
}
312
set_CMS_flag(CMS_cms_wants_token); // to provoke notifies
313
CGC_lock->wait(Mutex::_no_safepoint_check_flag, t_millis);
314
clear_CMS_flag(CMS_cms_wants_token);
315
assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
316
"Should not be set");
317
}
318
319
// Wait until the next synchronous GC, a concurrent full gc request,
320
// or a timeout, whichever is earlier.
321
void ConcurrentMarkSweepThread::wait_on_cms_lock_for_scavenge(long t_millis) {
322
// Wait time in millis or 0 value representing infinite wait for a scavenge
323
assert(t_millis >= 0, "Wait time for scavenge should be 0 or positive");
324
325
GenCollectedHeap* gch = GenCollectedHeap::heap();
326
double start_time_secs = os::elapsedTime();
327
double end_time_secs = start_time_secs + (t_millis / ((double) MILLIUNITS));
328
329
// Total collections count before waiting loop
330
unsigned int before_count;
331
{
332
MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
333
before_count = gch->total_collections();
334
}
335
336
unsigned int loop_count = 0;
337
338
while(!_should_terminate) {
339
double now_time = os::elapsedTime();
340
long wait_time_millis;
341
342
if(t_millis != 0) {
343
// New wait limit
344
wait_time_millis = (long) ((end_time_secs - now_time) * MILLIUNITS);
345
if(wait_time_millis <= 0) {
346
// Wait time is over
347
break;
348
}
349
} else {
350
// No wait limit, wait if necessary forever
351
wait_time_millis = 0;
352
}
353
354
// Wait until the next event or the remaining timeout
355
{
356
MutexLockerEx x(CGC_lock, Mutex::_no_safepoint_check_flag);
357
358
if (_should_terminate || _collector->_full_gc_requested) {
359
return;
360
}
361
set_CMS_flag(CMS_cms_wants_token); // to provoke notifies
362
assert(t_millis == 0 || wait_time_millis > 0, "Sanity");
363
CGC_lock->wait(Mutex::_no_safepoint_check_flag, wait_time_millis);
364
clear_CMS_flag(CMS_cms_wants_token);
365
assert(!CMS_flag_is_set(CMS_cms_has_token | CMS_cms_wants_token),
366
"Should not be set");
367
}
368
369
// Extra wait time check before entering the heap lock to get the collection count
370
if(t_millis != 0 && os::elapsedTime() >= end_time_secs) {
371
// Wait time is over
372
break;
373
}
374
375
// Total collections count after the event
376
unsigned int after_count;
377
{
378
MutexLockerEx hl(Heap_lock, Mutex::_no_safepoint_check_flag);
379
after_count = gch->total_collections();
380
}
381
382
if(before_count != after_count) {
383
// There was a collection - success
384
break;
385
}
386
387
// Too many loops warning
388
if(++loop_count == 0) {
389
warning("wait_on_cms_lock_for_scavenge() has looped %u times", loop_count - 1);
390
}
391
}
392
}
393
394
void ConcurrentMarkSweepThread::sleepBeforeNextCycle() {
395
while (!_should_terminate) {
396
if (CMSIncrementalMode) {
397
icms_wait();
398
if(CMSWaitDuration >= 0) {
399
// Wait until the next synchronous GC, a concurrent full gc
400
// request or a timeout, whichever is earlier.
401
wait_on_cms_lock_for_scavenge(CMSWaitDuration);
402
}
403
return;
404
} else {
405
if(CMSWaitDuration >= 0) {
406
// Wait until the next synchronous GC, a concurrent full gc
407
// request or a timeout, whichever is earlier.
408
wait_on_cms_lock_for_scavenge(CMSWaitDuration);
409
} else {
410
// Wait until any cms_lock event or check interval not to call shouldConcurrentCollect permanently
411
wait_on_cms_lock(CMSCheckInterval);
412
}
413
}
414
// Check if we should start a CMS collection cycle
415
if (_collector->shouldConcurrentCollect()) {
416
return;
417
}
418
// .. collection criterion not yet met, let's go back
419
// and wait some more
420
}
421
}
422
423
// Incremental CMS
424
void ConcurrentMarkSweepThread::start_icms() {
425
assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");
426
MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);
427
trace_state("start_icms");
428
_should_run = true;
429
iCMS_lock->notify_all();
430
}
431
432
void ConcurrentMarkSweepThread::stop_icms() {
433
assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");
434
MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);
435
if (!_should_stop) {
436
trace_state("stop_icms");
437
_should_stop = true;
438
_should_run = false;
439
asynchronous_yield_request();
440
iCMS_lock->notify_all();
441
}
442
}
443
444
void ConcurrentMarkSweepThread::icms_wait() {
445
assert(UseConcMarkSweepGC && CMSIncrementalMode, "just checking");
446
if (_should_stop && icms_is_enabled()) {
447
MutexLockerEx x(iCMS_lock, Mutex::_no_safepoint_check_flag);
448
trace_state("pause_icms");
449
_collector->stats().stop_cms_timer();
450
while(!_should_run && icms_is_enabled()) {
451
iCMS_lock->wait(Mutex::_no_safepoint_check_flag);
452
}
453
_collector->stats().start_cms_timer();
454
_should_stop = false;
455
trace_state("pause_icms end");
456
}
457
}
458
459
// Note: this method, although exported by the ConcurrentMarkSweepThread,
460
// which is a non-JavaThread, can only be called by a JavaThread.
461
// Currently this is done at vm creation time (post-vm-init) by the
462
// main/Primordial (Java)Thread.
463
// XXX Consider changing this in the future to allow the CMS thread
464
// itself to create this thread?
465
void ConcurrentMarkSweepThread::makeSurrogateLockerThread(TRAPS) {
466
assert(UseConcMarkSweepGC, "SLT thread needed only for CMS GC");
467
assert(_slt == NULL, "SLT already created");
468
_slt = SurrogateLockerThread::make(THREAD);
469
}
470
471