duke@435: /* xdono@631: * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved. duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. duke@435: * duke@435: * This code is free software; you can redistribute it and/or modify it duke@435: * under the terms of the GNU General Public License version 2 only, as duke@435: * published by the Free Software Foundation. duke@435: * duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License duke@435: * version 2 for more details (a copy is included in the LICENSE file that duke@435: * accompanied this code). duke@435: * duke@435: * You should have received a copy of the GNU General Public License version duke@435: * 2 along with this work; if not, write to the Free Software Foundation, duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. duke@435: * duke@435: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, duke@435: * CA 95054 USA or visit www.sun.com if you need additional information or duke@435: * have any questions. duke@435: * duke@435: */ duke@435: duke@435: # include "incls/_precompiled.incl" duke@435: # include "incls/_gcLocker.cpp.incl" duke@435: duke@435: volatile jint GC_locker::_jni_lock_count = 0; duke@435: volatile jint GC_locker::_lock_count = 0; duke@435: volatile bool GC_locker::_needs_gc = false; duke@435: volatile bool GC_locker::_doing_gc = false; duke@435: duke@435: void GC_locker::stall_until_clear() { duke@435: assert(!JavaThread::current()->in_critical(), "Would deadlock"); apetrusenko@574: if (PrintJNIGCStalls && PrintGCDetails) { apetrusenko@574: ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 apetrusenko@574: gclog_or_tty->print_cr( apetrusenko@574: "Allocation failed. Thread \"%s\" is stalled by JNI critical section.", apetrusenko@574: JavaThread::current()->name()); apetrusenko@574: } duke@435: MutexLocker ml(JNICritical_lock); duke@435: // Wait for _needs_gc to be cleared duke@435: while (GC_locker::needs_gc()) { duke@435: JNICritical_lock->wait(); duke@435: } duke@435: } duke@435: duke@435: void GC_locker::jni_lock_slow() { duke@435: MutexLocker mu(JNICritical_lock); duke@435: // Block entering threads if we know at least one thread is in a duke@435: // JNI critical region and we need a GC. duke@435: // We check that at least one thread is in a critical region before duke@435: // blocking because blocked threads are woken up by a thread exiting duke@435: // a JNI critical region. duke@435: while ((is_jni_active() && needs_gc()) || _doing_gc) { duke@435: JNICritical_lock->wait(); duke@435: } duke@435: jni_lock(); duke@435: } duke@435: duke@435: void GC_locker::jni_unlock_slow() { duke@435: MutexLocker mu(JNICritical_lock); duke@435: jni_unlock(); duke@435: if (needs_gc() && !is_jni_active()) { duke@435: // We're the last thread out. Cause a GC to occur. duke@435: // GC will also check is_active, so this check is not duke@435: // strictly needed. It's added here to make it clear that duke@435: // the GC will NOT be performed if any other caller duke@435: // of GC_locker::lock() still needs GC locked. duke@435: if (!is_active()) { duke@435: _doing_gc = true; duke@435: { duke@435: // Must give up the lock while at a safepoint duke@435: MutexUnlocker munlock(JNICritical_lock); duke@435: Universe::heap()->collect(GCCause::_gc_locker); duke@435: } duke@435: _doing_gc = false; duke@435: } duke@435: clear_needs_gc(); duke@435: JNICritical_lock->notify_all(); duke@435: } duke@435: } duke@435: duke@435: // Implementation of No_GC_Verifier duke@435: duke@435: #ifdef ASSERT duke@435: duke@435: No_GC_Verifier::No_GC_Verifier(bool verifygc) { duke@435: _verifygc = verifygc; duke@435: if (_verifygc) { duke@435: CollectedHeap* h = Universe::heap(); duke@435: assert(!h->is_gc_active(), "GC active during No_GC_Verifier"); duke@435: _old_invocations = h->total_collections(); duke@435: } duke@435: } duke@435: duke@435: duke@435: No_GC_Verifier::~No_GC_Verifier() { duke@435: if (_verifygc) { duke@435: CollectedHeap* h = Universe::heap(); duke@435: assert(!h->is_gc_active(), "GC active during No_GC_Verifier"); duke@435: if (_old_invocations != h->total_collections()) { duke@435: fatal("collection in a No_GC_Verifier secured function"); duke@435: } duke@435: } duke@435: } duke@435: duke@435: Pause_No_GC_Verifier::Pause_No_GC_Verifier(No_GC_Verifier * ngcv) { duke@435: _ngcv = ngcv; duke@435: if (_ngcv->_verifygc) { duke@435: // if we were verifying, then make sure that nothing is duke@435: // wrong before we "pause" verification duke@435: CollectedHeap* h = Universe::heap(); duke@435: assert(!h->is_gc_active(), "GC active during No_GC_Verifier"); duke@435: if (_ngcv->_old_invocations != h->total_collections()) { duke@435: fatal("collection in a No_GC_Verifier secured function"); duke@435: } duke@435: } duke@435: } duke@435: duke@435: duke@435: Pause_No_GC_Verifier::~Pause_No_GC_Verifier() { duke@435: if (_ngcv->_verifygc) { duke@435: // if we were verifying before, then reenable verification duke@435: CollectedHeap* h = Universe::heap(); duke@435: assert(!h->is_gc_active(), "GC active during No_GC_Verifier"); duke@435: _ngcv->_old_invocations = h->total_collections(); duke@435: } duke@435: } duke@435: duke@435: duke@435: // JRT_LEAF rules: duke@435: // A JRT_LEAF method may not interfere with safepointing by duke@435: // 1) acquiring or blocking on a Mutex or JavaLock - checked duke@435: // 2) allocating heap memory - checked duke@435: // 3) executing a VM operation - checked duke@435: // 4) executing a system call (including malloc) that could block or grab a lock duke@435: // 5) invoking GC duke@435: // 6) reaching a safepoint duke@435: // 7) running too long duke@435: // Nor may any method it calls. duke@435: JRT_Leaf_Verifier::JRT_Leaf_Verifier() duke@435: : No_Safepoint_Verifier(true, JRT_Leaf_Verifier::should_verify_GC()) duke@435: { duke@435: } duke@435: duke@435: JRT_Leaf_Verifier::~JRT_Leaf_Verifier() duke@435: { duke@435: } duke@435: duke@435: bool JRT_Leaf_Verifier::should_verify_GC() { duke@435: switch (JavaThread::current()->thread_state()) { duke@435: case _thread_in_Java: duke@435: // is in a leaf routine, there must be no safepoint. duke@435: return true; duke@435: case _thread_in_native: duke@435: // A native thread is not subject to safepoints. duke@435: // Even while it is in a leaf routine, GC is ok duke@435: return false; duke@435: default: duke@435: // Leaf routines cannot be called from other contexts. duke@435: ShouldNotReachHere(); duke@435: return false; duke@435: } duke@435: } duke@435: #endif