1 /*
   2  * Copyright (c) 1997, 2008, 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 "incls/_precompiled.incl"
  26 # include "incls/_gcLocker.cpp.incl"
  27 
  28 volatile jint GC_locker::_jni_lock_count = 0;
  29 volatile jint GC_locker::_lock_count     = 0;
  30 volatile bool GC_locker::_needs_gc       = false;
  31 volatile bool GC_locker::_doing_gc       = false;
  32 
  33 void GC_locker::stall_until_clear() {
  34   assert(!JavaThread::current()->in_critical(), "Would deadlock");
  35   if (PrintJNIGCStalls && PrintGCDetails) {
  36     ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
  37     gclog_or_tty->print_cr(
  38       "Allocation failed. Thread \"%s\" is stalled by JNI critical section.",
  39       JavaThread::current()->name());
  40   }
  41   MutexLocker   ml(JNICritical_lock);
  42   // Wait for _needs_gc  to be cleared
  43   while (GC_locker::needs_gc()) {
  44     JNICritical_lock->wait();
  45   }
  46 }
  47 
  48 void GC_locker::jni_lock_slow() {
  49   MutexLocker mu(JNICritical_lock);
  50   // Block entering threads if we know at least one thread is in a
  51   // JNI critical region and we need a GC.
  52   // We check that at least one thread is in a critical region before
  53   // blocking because blocked threads are woken up by a thread exiting
  54   // a JNI critical region.
  55   while ((is_jni_active() && needs_gc()) || _doing_gc) {
  56     JNICritical_lock->wait();
  57   }
  58   jni_lock();
  59 }
  60 
  61 void GC_locker::jni_unlock_slow() {
  62   MutexLocker mu(JNICritical_lock);
  63   jni_unlock();
  64   if (needs_gc() && !is_jni_active()) {
  65     // We're the last thread out. Cause a GC to occur.
  66     // GC will also check is_active, so this check is not
  67     // strictly needed. It's added here to make it clear that
  68     // the GC will NOT be performed if any other caller
  69     // of GC_locker::lock() still needs GC locked.
  70     if (!is_active()) {
  71       _doing_gc = true;
  72       {
  73         // Must give up the lock while at a safepoint
  74         MutexUnlocker munlock(JNICritical_lock);
  75         Universe::heap()->collect(GCCause::_gc_locker);
  76       }
  77       _doing_gc = false;
  78     }
  79     clear_needs_gc();
  80     JNICritical_lock->notify_all();
  81   }
  82 }
  83 
  84 // Implementation of No_GC_Verifier
  85 
  86 #ifdef ASSERT
  87 
  88 No_GC_Verifier::No_GC_Verifier(bool verifygc) {
  89   _verifygc = verifygc;
  90   if (_verifygc) {
  91     CollectedHeap* h = Universe::heap();
  92     assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
  93     _old_invocations = h->total_collections();
  94   }
  95 }
  96 
  97 
  98 No_GC_Verifier::~No_GC_Verifier() {
  99   if (_verifygc) {
 100     CollectedHeap* h = Universe::heap();
 101     assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
 102     if (_old_invocations != h->total_collections()) {
 103       fatal("collection in a No_GC_Verifier secured function");
 104     }
 105   }
 106 }
 107 
 108 Pause_No_GC_Verifier::Pause_No_GC_Verifier(No_GC_Verifier * ngcv) {
 109   _ngcv = ngcv;
 110   if (_ngcv->_verifygc) {
 111     // if we were verifying, then make sure that nothing is
 112     // wrong before we "pause" verification
 113     CollectedHeap* h = Universe::heap();
 114     assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
 115     if (_ngcv->_old_invocations != h->total_collections()) {
 116       fatal("collection in a No_GC_Verifier secured function");
 117     }
 118   }
 119 }
 120 
 121 
 122 Pause_No_GC_Verifier::~Pause_No_GC_Verifier() {
 123   if (_ngcv->_verifygc) {
 124     // if we were verifying before, then reenable verification
 125     CollectedHeap* h = Universe::heap();
 126     assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
 127     _ngcv->_old_invocations = h->total_collections();
 128   }
 129 }
 130 
 131 
 132 // JRT_LEAF rules:
 133 // A JRT_LEAF method may not interfere with safepointing by
 134 //   1) acquiring or blocking on a Mutex or JavaLock - checked
 135 //   2) allocating heap memory - checked
 136 //   3) executing a VM operation - checked
 137 //   4) executing a system call (including malloc) that could block or grab a lock
 138 //   5) invoking GC
 139 //   6) reaching a safepoint
 140 //   7) running too long
 141 // Nor may any method it calls.
 142 JRT_Leaf_Verifier::JRT_Leaf_Verifier()
 143   : No_Safepoint_Verifier(true, JRT_Leaf_Verifier::should_verify_GC())
 144 {
 145 }
 146 
 147 JRT_Leaf_Verifier::~JRT_Leaf_Verifier()
 148 {
 149 }
 150 
 151 bool JRT_Leaf_Verifier::should_verify_GC() {
 152   switch (JavaThread::current()->thread_state()) {
 153   case _thread_in_Java:
 154     // is in a leaf routine, there must be no safepoint.
 155     return true;
 156   case _thread_in_native:
 157     // A native thread is not subject to safepoints.
 158     // Even while it is in a leaf routine, GC is ok
 159     return false;
 160   default:
 161     // Leaf routines cannot be called from other contexts.
 162     ShouldNotReachHere();
 163     return false;
 164   }
 165 }
 166 #endif