src/share/vm/memory/gcLocker.cpp

changeset 0
f90c822e73f8
child 6876
710a3c8b516e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/vm/memory/gcLocker.cpp	Wed Apr 27 01:25:04 2016 +0800
     1.3 @@ -0,0 +1,219 @@
     1.4 +/*
     1.5 + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.
    1.11 + *
    1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.15 + * version 2 for more details (a copy is included in the LICENSE file that
    1.16 + * accompanied this code).
    1.17 + *
    1.18 + * You should have received a copy of the GNU General Public License version
    1.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.21 + *
    1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.23 + * or visit www.oracle.com if you need additional information or have any
    1.24 + * questions.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "precompiled.hpp"
    1.29 +#include "memory/gcLocker.inline.hpp"
    1.30 +#include "memory/resourceArea.hpp"
    1.31 +#include "memory/sharedHeap.hpp"
    1.32 +
    1.33 +volatile jint GC_locker::_jni_lock_count = 0;
    1.34 +volatile bool GC_locker::_needs_gc       = false;
    1.35 +volatile bool GC_locker::_doing_gc       = false;
    1.36 +
    1.37 +#ifdef ASSERT
    1.38 +volatile jint GC_locker::_debug_jni_lock_count = 0;
    1.39 +#endif
    1.40 +
    1.41 +
    1.42 +#ifdef ASSERT
    1.43 +void GC_locker::verify_critical_count() {
    1.44 +  if (SafepointSynchronize::is_at_safepoint()) {
    1.45 +    assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree");
    1.46 +    int count = 0;
    1.47 +    // Count the number of threads with critical operations in progress
    1.48 +    for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
    1.49 +      if (thr->in_critical()) {
    1.50 +        count++;
    1.51 +      }
    1.52 +    }
    1.53 +    if (_jni_lock_count != count) {
    1.54 +      tty->print_cr("critical counts don't match: %d != %d", _jni_lock_count, count);
    1.55 +      for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
    1.56 +        if (thr->in_critical()) {
    1.57 +          tty->print_cr(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());
    1.58 +        }
    1.59 +      }
    1.60 +    }
    1.61 +    assert(_jni_lock_count == count, "must be equal");
    1.62 +  }
    1.63 +}
    1.64 +#endif
    1.65 +
    1.66 +bool GC_locker::check_active_before_gc() {
    1.67 +  assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
    1.68 +  if (is_active() && !_needs_gc) {
    1.69 +    verify_critical_count();
    1.70 +    _needs_gc = true;
    1.71 +    if (PrintJNIGCStalls && PrintGCDetails) {
    1.72 +      ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
    1.73 +      gclog_or_tty->print_cr("%.3f: Setting _needs_gc. Thread \"%s\" %d locked.",
    1.74 +                             gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);
    1.75 +    }
    1.76 +
    1.77 +  }
    1.78 +  return is_active();
    1.79 +}
    1.80 +
    1.81 +void GC_locker::stall_until_clear() {
    1.82 +  assert(!JavaThread::current()->in_critical(), "Would deadlock");
    1.83 +  MutexLocker   ml(JNICritical_lock);
    1.84 +
    1.85 +  if (needs_gc()) {
    1.86 +    if (PrintJNIGCStalls && PrintGCDetails) {
    1.87 +      ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
    1.88 +      gclog_or_tty->print_cr("%.3f: Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.",
    1.89 +                             gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);
    1.90 +    }
    1.91 +  }
    1.92 +
    1.93 +  // Wait for _needs_gc  to be cleared
    1.94 +  while (needs_gc()) {
    1.95 +    JNICritical_lock->wait();
    1.96 +  }
    1.97 +}
    1.98 +
    1.99 +void GC_locker::jni_lock(JavaThread* thread) {
   1.100 +  assert(!thread->in_critical(), "shouldn't currently be in a critical region");
   1.101 +  MutexLocker mu(JNICritical_lock);
   1.102 +  // Block entering threads if we know at least one thread is in a
   1.103 +  // JNI critical region and we need a GC.
   1.104 +  // We check that at least one thread is in a critical region before
   1.105 +  // blocking because blocked threads are woken up by a thread exiting
   1.106 +  // a JNI critical region.
   1.107 +  while (is_active_and_needs_gc() || _doing_gc) {
   1.108 +    JNICritical_lock->wait();
   1.109 +  }
   1.110 +  thread->enter_critical();
   1.111 +  _jni_lock_count++;
   1.112 +  increment_debug_jni_lock_count();
   1.113 +}
   1.114 +
   1.115 +void GC_locker::jni_unlock(JavaThread* thread) {
   1.116 +  assert(thread->in_last_critical(), "should be exiting critical region");
   1.117 +  MutexLocker mu(JNICritical_lock);
   1.118 +  _jni_lock_count--;
   1.119 +  decrement_debug_jni_lock_count();
   1.120 +  thread->exit_critical();
   1.121 +  if (needs_gc() && !is_active_internal()) {
   1.122 +    // We're the last thread out. Cause a GC to occur.
   1.123 +    _doing_gc = true;
   1.124 +    {
   1.125 +      // Must give up the lock while at a safepoint
   1.126 +      MutexUnlocker munlock(JNICritical_lock);
   1.127 +      if (PrintJNIGCStalls && PrintGCDetails) {
   1.128 +        ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
   1.129 +        gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked",
   1.130 +            gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count);
   1.131 +      }
   1.132 +      Universe::heap()->collect(GCCause::_gc_locker);
   1.133 +    }
   1.134 +    _doing_gc = false;
   1.135 +    _needs_gc = false;
   1.136 +    JNICritical_lock->notify_all();
   1.137 +  }
   1.138 +}
   1.139 +
   1.140 +// Implementation of No_GC_Verifier
   1.141 +
   1.142 +#ifdef ASSERT
   1.143 +
   1.144 +No_GC_Verifier::No_GC_Verifier(bool verifygc) {
   1.145 +  _verifygc = verifygc;
   1.146 +  if (_verifygc) {
   1.147 +    CollectedHeap* h = Universe::heap();
   1.148 +    assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
   1.149 +    _old_invocations = h->total_collections();
   1.150 +  }
   1.151 +}
   1.152 +
   1.153 +
   1.154 +No_GC_Verifier::~No_GC_Verifier() {
   1.155 +  if (_verifygc) {
   1.156 +    CollectedHeap* h = Universe::heap();
   1.157 +    assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
   1.158 +    if (_old_invocations != h->total_collections()) {
   1.159 +      fatal("collection in a No_GC_Verifier secured function");
   1.160 +    }
   1.161 +  }
   1.162 +}
   1.163 +
   1.164 +Pause_No_GC_Verifier::Pause_No_GC_Verifier(No_GC_Verifier * ngcv) {
   1.165 +  _ngcv = ngcv;
   1.166 +  if (_ngcv->_verifygc) {
   1.167 +    // if we were verifying, then make sure that nothing is
   1.168 +    // wrong before we "pause" verification
   1.169 +    CollectedHeap* h = Universe::heap();
   1.170 +    assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
   1.171 +    if (_ngcv->_old_invocations != h->total_collections()) {
   1.172 +      fatal("collection in a No_GC_Verifier secured function");
   1.173 +    }
   1.174 +  }
   1.175 +}
   1.176 +
   1.177 +
   1.178 +Pause_No_GC_Verifier::~Pause_No_GC_Verifier() {
   1.179 +  if (_ngcv->_verifygc) {
   1.180 +    // if we were verifying before, then reenable verification
   1.181 +    CollectedHeap* h = Universe::heap();
   1.182 +    assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
   1.183 +    _ngcv->_old_invocations = h->total_collections();
   1.184 +  }
   1.185 +}
   1.186 +
   1.187 +
   1.188 +// JRT_LEAF rules:
   1.189 +// A JRT_LEAF method may not interfere with safepointing by
   1.190 +//   1) acquiring or blocking on a Mutex or JavaLock - checked
   1.191 +//   2) allocating heap memory - checked
   1.192 +//   3) executing a VM operation - checked
   1.193 +//   4) executing a system call (including malloc) that could block or grab a lock
   1.194 +//   5) invoking GC
   1.195 +//   6) reaching a safepoint
   1.196 +//   7) running too long
   1.197 +// Nor may any method it calls.
   1.198 +JRT_Leaf_Verifier::JRT_Leaf_Verifier()
   1.199 +  : No_Safepoint_Verifier(true, JRT_Leaf_Verifier::should_verify_GC())
   1.200 +{
   1.201 +}
   1.202 +
   1.203 +JRT_Leaf_Verifier::~JRT_Leaf_Verifier()
   1.204 +{
   1.205 +}
   1.206 +
   1.207 +bool JRT_Leaf_Verifier::should_verify_GC() {
   1.208 +  switch (JavaThread::current()->thread_state()) {
   1.209 +  case _thread_in_Java:
   1.210 +    // is in a leaf routine, there must be no safepoint.
   1.211 +    return true;
   1.212 +  case _thread_in_native:
   1.213 +    // A native thread is not subject to safepoints.
   1.214 +    // Even while it is in a leaf routine, GC is ok
   1.215 +    return false;
   1.216 +  default:
   1.217 +    // Leaf routines cannot be called from other contexts.
   1.218 +    ShouldNotReachHere();
   1.219 +    return false;
   1.220 +  }
   1.221 +}
   1.222 +#endif

mercurial