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/memory/gcLocker.cpp
32285 views
1
/*
2
* Copyright (c) 1997, 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 "memory/gcLocker.inline.hpp"
27
#include "memory/resourceArea.hpp"
28
#include "memory/sharedHeap.hpp"
29
#include "runtime/thread.inline.hpp"
30
31
volatile jint GC_locker::_jni_lock_count = 0;
32
volatile bool GC_locker::_needs_gc = false;
33
volatile bool GC_locker::_doing_gc = false;
34
unsigned int GC_locker::_total_collections = 0;
35
36
#ifdef ASSERT
37
volatile jint GC_locker::_debug_jni_lock_count = 0;
38
#endif
39
40
41
#ifdef ASSERT
42
void GC_locker::verify_critical_count() {
43
if (SafepointSynchronize::is_at_safepoint()) {
44
assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree");
45
int count = 0;
46
// Count the number of threads with critical operations in progress
47
for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
48
if (thr->in_critical()) {
49
count++;
50
}
51
}
52
if (_jni_lock_count != count) {
53
tty->print_cr("critical counts don't match: %d != %d", _jni_lock_count, count);
54
for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
55
if (thr->in_critical()) {
56
tty->print_cr(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());
57
}
58
}
59
}
60
assert(_jni_lock_count == count, "must be equal");
61
}
62
}
63
#endif
64
65
bool GC_locker::check_active_before_gc() {
66
assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
67
if (is_active() && !_needs_gc) {
68
verify_critical_count();
69
_needs_gc = true;
70
if (PrintJNIGCStalls && PrintGCDetails) {
71
ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
72
gclog_or_tty->print_cr("%.3f: Setting _needs_gc. Thread \"%s\" %d locked.",
73
gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);
74
}
75
76
}
77
return is_active();
78
}
79
80
void GC_locker::stall_until_clear() {
81
assert(!JavaThread::current()->in_critical(), "Would deadlock");
82
MutexLocker ml(JNICritical_lock);
83
84
if (needs_gc()) {
85
if (PrintJNIGCStalls && PrintGCDetails) {
86
ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
87
gclog_or_tty->print_cr("%.3f: Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.",
88
gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);
89
}
90
}
91
92
// Wait for _needs_gc to be cleared
93
while (needs_gc()) {
94
JNICritical_lock->wait();
95
}
96
}
97
98
bool GC_locker::should_discard(GCCause::Cause cause, uint total_collections) {
99
return (cause == GCCause::_gc_locker) &&
100
(_total_collections != total_collections);
101
}
102
103
void GC_locker::jni_lock(JavaThread* thread) {
104
assert(!thread->in_critical(), "shouldn't currently be in a critical region");
105
MutexLocker mu(JNICritical_lock);
106
// Block entering threads if we know at least one thread is in a
107
// JNI critical region and we need a GC.
108
// We check that at least one thread is in a critical region before
109
// blocking because blocked threads are woken up by a thread exiting
110
// a JNI critical region.
111
while (is_active_and_needs_gc() || _doing_gc) {
112
JNICritical_lock->wait();
113
}
114
thread->enter_critical();
115
_jni_lock_count++;
116
increment_debug_jni_lock_count();
117
}
118
119
void GC_locker::jni_unlock(JavaThread* thread) {
120
assert(thread->in_last_critical(), "should be exiting critical region");
121
MutexLocker mu(JNICritical_lock);
122
_jni_lock_count--;
123
decrement_debug_jni_lock_count();
124
thread->exit_critical();
125
if (needs_gc() && !is_active_internal()) {
126
// We're the last thread out. Request a GC.
127
// Capture the current total collections, to allow detection of
128
// other collections that make this one unnecessary. The value of
129
// total_collections() is only changed at a safepoint, so there
130
// must not be a safepoint between the lock becoming inactive and
131
// getting the count, else there may be unnecessary GCLocker GCs.
132
_total_collections = Universe::heap()->total_collections();
133
_doing_gc = true;
134
{
135
// Must give up the lock while at a safepoint
136
MutexUnlocker munlock(JNICritical_lock);
137
if (PrintJNIGCStalls && PrintGCDetails) {
138
ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
139
gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked",
140
gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);
141
}
142
Universe::heap()->collect(GCCause::_gc_locker);
143
}
144
_doing_gc = false;
145
_needs_gc = false;
146
JNICritical_lock->notify_all();
147
}
148
}
149
150
// Implementation of No_GC_Verifier
151
152
#ifdef ASSERT
153
154
No_GC_Verifier::No_GC_Verifier(bool verifygc) {
155
_verifygc = verifygc;
156
if (_verifygc) {
157
CollectedHeap* h = Universe::heap();
158
assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
159
_old_invocations = h->total_collections();
160
}
161
}
162
163
164
No_GC_Verifier::~No_GC_Verifier() {
165
if (_verifygc) {
166
CollectedHeap* h = Universe::heap();
167
assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
168
if (_old_invocations != h->total_collections()) {
169
fatal("collection in a No_GC_Verifier secured function");
170
}
171
}
172
}
173
174
Pause_No_GC_Verifier::Pause_No_GC_Verifier(No_GC_Verifier * ngcv) {
175
_ngcv = ngcv;
176
if (_ngcv->_verifygc) {
177
// if we were verifying, then make sure that nothing is
178
// wrong before we "pause" verification
179
CollectedHeap* h = Universe::heap();
180
assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
181
if (_ngcv->_old_invocations != h->total_collections()) {
182
fatal("collection in a No_GC_Verifier secured function");
183
}
184
}
185
}
186
187
188
Pause_No_GC_Verifier::~Pause_No_GC_Verifier() {
189
if (_ngcv->_verifygc) {
190
// if we were verifying before, then reenable verification
191
CollectedHeap* h = Universe::heap();
192
assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
193
_ngcv->_old_invocations = h->total_collections();
194
}
195
}
196
197
198
// JRT_LEAF rules:
199
// A JRT_LEAF method may not interfere with safepointing by
200
// 1) acquiring or blocking on a Mutex or JavaLock - checked
201
// 2) allocating heap memory - checked
202
// 3) executing a VM operation - checked
203
// 4) executing a system call (including malloc) that could block or grab a lock
204
// 5) invoking GC
205
// 6) reaching a safepoint
206
// 7) running too long
207
// Nor may any method it calls.
208
JRT_Leaf_Verifier::JRT_Leaf_Verifier()
209
: No_Safepoint_Verifier(true, JRT_Leaf_Verifier::should_verify_GC())
210
{
211
}
212
213
JRT_Leaf_Verifier::~JRT_Leaf_Verifier()
214
{
215
}
216
217
bool JRT_Leaf_Verifier::should_verify_GC() {
218
switch (JavaThread::current()->thread_state()) {
219
case _thread_in_Java:
220
// is in a leaf routine, there must be no safepoint.
221
return true;
222
case _thread_in_native:
223
// A native thread is not subject to safepoints.
224
// Even while it is in a leaf routine, GC is ok
225
return false;
226
default:
227
// Leaf routines cannot be called from other contexts.
228
ShouldNotReachHere();
229
return false;
230
}
231
}
232
#endif
233
234