Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/memory/gcLocker.cpp
32285 views
/*1* Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#include "precompiled.hpp"25#include "memory/gcLocker.inline.hpp"26#include "memory/resourceArea.hpp"27#include "memory/sharedHeap.hpp"28#include "runtime/thread.inline.hpp"2930volatile jint GC_locker::_jni_lock_count = 0;31volatile bool GC_locker::_needs_gc = false;32volatile bool GC_locker::_doing_gc = false;33unsigned int GC_locker::_total_collections = 0;3435#ifdef ASSERT36volatile jint GC_locker::_debug_jni_lock_count = 0;37#endif383940#ifdef ASSERT41void GC_locker::verify_critical_count() {42if (SafepointSynchronize::is_at_safepoint()) {43assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree");44int count = 0;45// Count the number of threads with critical operations in progress46for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {47if (thr->in_critical()) {48count++;49}50}51if (_jni_lock_count != count) {52tty->print_cr("critical counts don't match: %d != %d", _jni_lock_count, count);53for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {54if (thr->in_critical()) {55tty->print_cr(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());56}57}58}59assert(_jni_lock_count == count, "must be equal");60}61}62#endif6364bool GC_locker::check_active_before_gc() {65assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");66if (is_active() && !_needs_gc) {67verify_critical_count();68_needs_gc = true;69if (PrintJNIGCStalls && PrintGCDetails) {70ResourceMark rm; // JavaThread::name() allocates to convert to UTF871gclog_or_tty->print_cr("%.3f: Setting _needs_gc. Thread \"%s\" %d locked.",72gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);73}7475}76return is_active();77}7879void GC_locker::stall_until_clear() {80assert(!JavaThread::current()->in_critical(), "Would deadlock");81MutexLocker ml(JNICritical_lock);8283if (needs_gc()) {84if (PrintJNIGCStalls && PrintGCDetails) {85ResourceMark rm; // JavaThread::name() allocates to convert to UTF886gclog_or_tty->print_cr("%.3f: Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.",87gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);88}89}9091// Wait for _needs_gc to be cleared92while (needs_gc()) {93JNICritical_lock->wait();94}95}9697bool GC_locker::should_discard(GCCause::Cause cause, uint total_collections) {98return (cause == GCCause::_gc_locker) &&99(_total_collections != total_collections);100}101102void GC_locker::jni_lock(JavaThread* thread) {103assert(!thread->in_critical(), "shouldn't currently be in a critical region");104MutexLocker mu(JNICritical_lock);105// Block entering threads if we know at least one thread is in a106// JNI critical region and we need a GC.107// We check that at least one thread is in a critical region before108// blocking because blocked threads are woken up by a thread exiting109// a JNI critical region.110while (is_active_and_needs_gc() || _doing_gc) {111JNICritical_lock->wait();112}113thread->enter_critical();114_jni_lock_count++;115increment_debug_jni_lock_count();116}117118void GC_locker::jni_unlock(JavaThread* thread) {119assert(thread->in_last_critical(), "should be exiting critical region");120MutexLocker mu(JNICritical_lock);121_jni_lock_count--;122decrement_debug_jni_lock_count();123thread->exit_critical();124if (needs_gc() && !is_active_internal()) {125// We're the last thread out. Request a GC.126// Capture the current total collections, to allow detection of127// other collections that make this one unnecessary. The value of128// total_collections() is only changed at a safepoint, so there129// must not be a safepoint between the lock becoming inactive and130// getting the count, else there may be unnecessary GCLocker GCs.131_total_collections = Universe::heap()->total_collections();132_doing_gc = true;133{134// Must give up the lock while at a safepoint135MutexUnlocker munlock(JNICritical_lock);136if (PrintJNIGCStalls && PrintGCDetails) {137ResourceMark rm; // JavaThread::name() allocates to convert to UTF8138gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked",139gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);140}141Universe::heap()->collect(GCCause::_gc_locker);142}143_doing_gc = false;144_needs_gc = false;145JNICritical_lock->notify_all();146}147}148149// Implementation of No_GC_Verifier150151#ifdef ASSERT152153No_GC_Verifier::No_GC_Verifier(bool verifygc) {154_verifygc = verifygc;155if (_verifygc) {156CollectedHeap* h = Universe::heap();157assert(!h->is_gc_active(), "GC active during No_GC_Verifier");158_old_invocations = h->total_collections();159}160}161162163No_GC_Verifier::~No_GC_Verifier() {164if (_verifygc) {165CollectedHeap* h = Universe::heap();166assert(!h->is_gc_active(), "GC active during No_GC_Verifier");167if (_old_invocations != h->total_collections()) {168fatal("collection in a No_GC_Verifier secured function");169}170}171}172173Pause_No_GC_Verifier::Pause_No_GC_Verifier(No_GC_Verifier * ngcv) {174_ngcv = ngcv;175if (_ngcv->_verifygc) {176// if we were verifying, then make sure that nothing is177// wrong before we "pause" verification178CollectedHeap* h = Universe::heap();179assert(!h->is_gc_active(), "GC active during No_GC_Verifier");180if (_ngcv->_old_invocations != h->total_collections()) {181fatal("collection in a No_GC_Verifier secured function");182}183}184}185186187Pause_No_GC_Verifier::~Pause_No_GC_Verifier() {188if (_ngcv->_verifygc) {189// if we were verifying before, then reenable verification190CollectedHeap* h = Universe::heap();191assert(!h->is_gc_active(), "GC active during No_GC_Verifier");192_ngcv->_old_invocations = h->total_collections();193}194}195196197// JRT_LEAF rules:198// A JRT_LEAF method may not interfere with safepointing by199// 1) acquiring or blocking on a Mutex or JavaLock - checked200// 2) allocating heap memory - checked201// 3) executing a VM operation - checked202// 4) executing a system call (including malloc) that could block or grab a lock203// 5) invoking GC204// 6) reaching a safepoint205// 7) running too long206// Nor may any method it calls.207JRT_Leaf_Verifier::JRT_Leaf_Verifier()208: No_Safepoint_Verifier(true, JRT_Leaf_Verifier::should_verify_GC())209{210}211212JRT_Leaf_Verifier::~JRT_Leaf_Verifier()213{214}215216bool JRT_Leaf_Verifier::should_verify_GC() {217switch (JavaThread::current()->thread_state()) {218case _thread_in_Java:219// is in a leaf routine, there must be no safepoint.220return true;221case _thread_in_native:222// A native thread is not subject to safepoints.223// Even while it is in a leaf routine, GC is ok224return false;225default:226// Leaf routines cannot be called from other contexts.227ShouldNotReachHere();228return false;229}230}231#endif232233234