2
* Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
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.
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).
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.
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
25
#include "precompiled.hpp"
26
#include "gc/shared/collectedHeap.hpp"
27
#include "gc/shared/gcLocker.hpp"
28
#include "gc/shared/gcTrace.hpp"
29
#include "memory/resourceArea.hpp"
30
#include "memory/universe.hpp"
31
#include "logging/log.hpp"
32
#include "runtime/atomic.hpp"
33
#include "runtime/javaThread.inline.hpp"
34
#include "runtime/safepoint.hpp"
35
#include "runtime/threadSMR.hpp"
37
volatile jint GCLocker::_jni_lock_count = 0;
38
volatile bool GCLocker::_needs_gc = false;
39
unsigned int GCLocker::_total_collections = 0;
42
volatile jint GCLocker::_debug_jni_lock_count = 0;
47
void GCLocker::verify_critical_count() {
48
if (SafepointSynchronize::is_at_safepoint()) {
49
assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree");
51
// Count the number of threads with critical operations in progress
52
JavaThreadIteratorWithHandle jtiwh;
53
for (; JavaThread *thr = jtiwh.next(); ) {
54
if (thr->in_critical()) {
58
if (_jni_lock_count != count) {
59
log_error(gc, verify)("critical counts don't match: %d != %d", _jni_lock_count, count);
61
for (; JavaThread *thr = jtiwh.next(); ) {
62
if (thr->in_critical()) {
63
log_error(gc, verify)(PTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());
67
assert(_jni_lock_count == count, "must be equal");
71
// In debug mode track the locking state at all times
72
void GCLocker::increment_debug_jni_lock_count() {
73
assert(_debug_jni_lock_count >= 0, "bad value");
74
Atomic::inc(&_debug_jni_lock_count);
77
void GCLocker::decrement_debug_jni_lock_count() {
78
assert(_debug_jni_lock_count > 0, "bad value");
79
Atomic::dec(&_debug_jni_lock_count);
83
void GCLocker::log_debug_jni(const char* msg) {
86
ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
87
log.debug("%s Thread \"%s\" %d locked.", msg, Thread::current()->name(), _jni_lock_count);
91
bool GCLocker::is_at_safepoint() {
92
return SafepointSynchronize::is_at_safepoint();
95
bool GCLocker::check_active_before_gc() {
96
assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
97
if (is_active() && !_needs_gc) {
98
verify_critical_count();
100
GCLockerTracer::start_gc_locker(_jni_lock_count);
101
log_debug_jni("Setting _needs_gc.");
106
void GCLocker::stall_until_clear() {
107
assert(!JavaThread::current()->in_critical(), "Would deadlock");
108
MonitorLocker ml(JNICritical_lock);
111
GCLockerTracer::inc_stall_count();
112
log_debug_jni("Allocation failed. Thread stalled by JNI critical section.");
115
// Wait for _needs_gc to be cleared
121
bool GCLocker::should_discard(GCCause::Cause cause, uint total_collections) {
122
return (cause == GCCause::_gc_locker) &&
123
(_total_collections != total_collections);
126
void GCLocker::jni_lock(JavaThread* thread) {
127
assert(!thread->in_critical(), "shouldn't currently be in a critical region");
128
MonitorLocker ml(JNICritical_lock);
129
// Block entering threads if there's a pending GC request.
131
// There's at least one thread that has not left the critical region (CR)
132
// completely. When that last thread (no new threads can enter CR due to the
133
// blocking) exits CR, it calls `jni_unlock`, which sets `_needs_gc`
134
// to false and wakes up all blocked threads.
135
// We would like to assert #threads in CR to be > 0, `_jni_lock_count > 0`
136
// in the code, but it's too strong; it's possible that the last thread
137
// has called `jni_unlock`, but not yet finished the call, e.g. initiating
138
// a GCCause::_gc_locker GC.
141
thread->enter_critical();
143
increment_debug_jni_lock_count();
146
void GCLocker::jni_unlock(JavaThread* thread) {
147
assert(thread->in_last_critical(), "should be exiting critical region");
148
MutexLocker mu(JNICritical_lock);
150
decrement_debug_jni_lock_count();
151
thread->exit_critical();
152
if (needs_gc() && !is_active_internal()) {
153
// We're the last thread out. Request a GC.
154
// Capture the current total collections, to allow detection of
155
// other collections that make this one unnecessary. The value of
156
// total_collections() is only changed at a safepoint, so there
157
// must not be a safepoint between the lock becoming inactive and
158
// getting the count, else there may be unnecessary GCLocker GCs.
159
_total_collections = Universe::heap()->total_collections();
160
GCLockerTracer::report_gc_locker();
162
// Must give up the lock while at a safepoint
163
MutexUnlocker munlock(JNICritical_lock);
164
log_debug_jni("Performing GC after exiting critical section.");
165
Universe::heap()->collect(GCCause::_gc_locker);
168
JNICritical_lock->notify_all();