src/share/vm/memory/gcLocker.cpp

changeset 3494
1a2723f7ad8e
parent 2314
f95d63e2154a
child 3500
0382d2b469b2
     1.1 --- a/src/share/vm/memory/gcLocker.cpp	Thu Jan 26 19:39:08 2012 -0800
     1.2 +++ b/src/share/vm/memory/gcLocker.cpp	Sun Jan 29 16:46:04 2012 -0800
     1.3 @@ -1,5 +1,5 @@
     1.4  /*
     1.5 - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
     1.6 + * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
     1.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.8   *
     1.9   * This code is free software; you can redistribute it and/or modify it
    1.10 @@ -31,38 +31,93 @@
    1.11  volatile jint GC_locker::_lock_count     = 0;
    1.12  volatile bool GC_locker::_needs_gc       = false;
    1.13  volatile bool GC_locker::_doing_gc       = false;
    1.14 +jlong GC_locker::_wait_begin = 0;
    1.15 +
    1.16 +#ifdef ASSERT
    1.17 +volatile jint GC_locker::_debug_jni_lock_count = 0;
    1.18 +#endif
    1.19 +
    1.20 +
    1.21 +#ifdef ASSERT
    1.22 +void GC_locker::verify_critical_count() {
    1.23 +  if (SafepointSynchronize::is_at_safepoint()) {
    1.24 +    assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree");
    1.25 +    int count = 0;
    1.26 +    // Count the number of threads with critical operations in progress
    1.27 +    for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
    1.28 +      if (thr->in_critical()) {
    1.29 +        count++;
    1.30 +      }
    1.31 +    }
    1.32 +    if (_jni_lock_count != count) {
    1.33 +      tty->print_cr("critical counts don't match: %d != %d", _jni_lock_count, count);
    1.34 +      for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
    1.35 +        if (thr->in_critical()) {
    1.36 +          tty->print_cr(INTPTR_FORMAT " in_critical %d", thr, thr->in_critical());
    1.37 +        }
    1.38 +      }
    1.39 +    }
    1.40 +    assert(_jni_lock_count == count, "must be equal");
    1.41 +  }
    1.42 +}
    1.43 +#endif
    1.44 +
    1.45 +bool GC_locker::check_active_before_gc() {
    1.46 +  assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
    1.47 +  if (is_active() && !_needs_gc) {
    1.48 +    verify_critical_count();
    1.49 +    _needs_gc = true;
    1.50 +    if (PrintJNIGCStalls && PrintGCDetails) {
    1.51 +      ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
    1.52 +      _wait_begin = tty->time_stamp().milliseconds();
    1.53 +      gclog_or_tty->print_cr(INT64_FORMAT ": Setting _needs_gc. Thread \"%s\" %d locked.",
    1.54 +                             _wait_begin, Thread::current()->name(), _jni_lock_count);
    1.55 +    }
    1.56 +
    1.57 +  }
    1.58 +  return is_active();
    1.59 +}
    1.60  
    1.61  void GC_locker::stall_until_clear() {
    1.62    assert(!JavaThread::current()->in_critical(), "Would deadlock");
    1.63 -  if (PrintJNIGCStalls && PrintGCDetails) {
    1.64 -    ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
    1.65 -    gclog_or_tty->print_cr(
    1.66 -      "Allocation failed. Thread \"%s\" is stalled by JNI critical section.",
    1.67 -      JavaThread::current()->name());
    1.68 +  MutexLocker   ml(JNICritical_lock);
    1.69 +
    1.70 +  if (needs_gc()) {
    1.71 +    if (PrintJNIGCStalls && PrintGCDetails) {
    1.72 +      ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
    1.73 +      gclog_or_tty->print_cr(INT64_FORMAT ": Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.",
    1.74 +                             tty->time_stamp().milliseconds() - _wait_begin, Thread::current()->name(), _jni_lock_count);
    1.75 +    }
    1.76    }
    1.77 -  MutexLocker   ml(JNICritical_lock);
    1.78 +
    1.79    // Wait for _needs_gc  to be cleared
    1.80 -  while (GC_locker::needs_gc()) {
    1.81 +  while (needs_gc()) {
    1.82      JNICritical_lock->wait();
    1.83    }
    1.84  }
    1.85  
    1.86 -void GC_locker::jni_lock_slow() {
    1.87 +void GC_locker::jni_lock(JavaThread* thread) {
    1.88 +  assert(!thread->in_critical(), "shouldn't currently be in a critical region");
    1.89    MutexLocker mu(JNICritical_lock);
    1.90    // Block entering threads if we know at least one thread is in a
    1.91    // JNI critical region and we need a GC.
    1.92    // We check that at least one thread is in a critical region before
    1.93    // blocking because blocked threads are woken up by a thread exiting
    1.94    // a JNI critical region.
    1.95 -  while ((is_jni_active() && needs_gc()) || _doing_gc) {
    1.96 +  while ((needs_gc() && is_jni_active()) || _doing_gc) {
    1.97      JNICritical_lock->wait();
    1.98    }
    1.99 -  jni_lock();
   1.100 +  thread->enter_critical();
   1.101 +  _jni_lock_count++;
   1.102 +  increment_debug_jni_lock_count();
   1.103  }
   1.104  
   1.105 -void GC_locker::jni_unlock_slow() {
   1.106 +void GC_locker::jni_unlock(JavaThread* thread) {
   1.107 +  assert(thread->in_last_critical(), "should be exiting critical region");
   1.108    MutexLocker mu(JNICritical_lock);
   1.109 -  jni_unlock();
   1.110 +  _jni_lock_count--;
   1.111 +  decrement_debug_jni_lock_count();
   1.112 +  thread->exit_critical();
   1.113    if (needs_gc() && !is_jni_active()) {
   1.114      // We're the last thread out. Cause a GC to occur.
   1.115      // GC will also check is_active, so this check is not
   1.116 @@ -74,11 +129,17 @@
   1.117        {
   1.118          // Must give up the lock while at a safepoint
   1.119          MutexUnlocker munlock(JNICritical_lock);
   1.120 +        if (PrintJNIGCStalls && PrintGCDetails) {
   1.121 +          ResourceMark rm; // JavaThread::name() allocates to convert to UTF8
   1.122 +          gclog_or_tty->print_cr(INT64_FORMAT ": Thread \"%s\" is performing GC after exiting critical section, %d locked",
   1.123 +                                 tty->time_stamp().milliseconds() - _wait_begin, Thread::current()->name(), _jni_lock_count);
   1.124 +        }
   1.125          Universe::heap()->collect(GCCause::_gc_locker);
   1.126        }
   1.127        _doing_gc = false;
   1.128      }
   1.129 -    clear_needs_gc();
   1.130 +
   1.131 +    _needs_gc = false;
   1.132      JNICritical_lock->notify_all();
   1.133    }
   1.134  }

mercurial