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 }