26 #include "memory/gcLocker.inline.hpp" |
26 #include "memory/gcLocker.inline.hpp" |
27 #include "memory/resourceArea.hpp" |
27 #include "memory/resourceArea.hpp" |
28 #include "memory/sharedHeap.hpp" |
28 #include "memory/sharedHeap.hpp" |
29 |
29 |
30 volatile jint GC_locker::_jni_lock_count = 0; |
30 volatile jint GC_locker::_jni_lock_count = 0; |
31 volatile jint GC_locker::_lock_count = 0; |
|
32 volatile bool GC_locker::_needs_gc = false; |
31 volatile bool GC_locker::_needs_gc = false; |
33 volatile bool GC_locker::_doing_gc = false; |
32 volatile bool GC_locker::_doing_gc = false; |
34 |
33 |
35 #ifdef ASSERT |
34 #ifdef ASSERT |
36 volatile jint GC_locker::_debug_jni_lock_count = 0; |
35 volatile jint GC_locker::_debug_jni_lock_count = 0; |
100 // Block entering threads if we know at least one thread is in a |
99 // Block entering threads if we know at least one thread is in a |
101 // JNI critical region and we need a GC. |
100 // JNI critical region and we need a GC. |
102 // We check that at least one thread is in a critical region before |
101 // We check that at least one thread is in a critical region before |
103 // blocking because blocked threads are woken up by a thread exiting |
102 // blocking because blocked threads are woken up by a thread exiting |
104 // a JNI critical region. |
103 // a JNI critical region. |
105 while ((needs_gc() && is_jni_active()) || _doing_gc) { |
104 while (is_active_and_needs_gc() || _doing_gc) { |
106 JNICritical_lock->wait(); |
105 JNICritical_lock->wait(); |
107 } |
106 } |
108 thread->enter_critical(); |
107 thread->enter_critical(); |
109 _jni_lock_count++; |
108 _jni_lock_count++; |
110 increment_debug_jni_lock_count(); |
109 increment_debug_jni_lock_count(); |
114 assert(thread->in_last_critical(), "should be exiting critical region"); |
113 assert(thread->in_last_critical(), "should be exiting critical region"); |
115 MutexLocker mu(JNICritical_lock); |
114 MutexLocker mu(JNICritical_lock); |
116 _jni_lock_count--; |
115 _jni_lock_count--; |
117 decrement_debug_jni_lock_count(); |
116 decrement_debug_jni_lock_count(); |
118 thread->exit_critical(); |
117 thread->exit_critical(); |
119 if (needs_gc() && !is_jni_active()) { |
118 if (needs_gc() && !is_active_internal()) { |
120 // We're the last thread out. Cause a GC to occur. |
119 // We're the last thread out. Cause a GC to occur. |
121 // GC will also check is_active, so this check is not |
120 _doing_gc = true; |
122 // strictly needed. It's added here to make it clear that |
121 { |
123 // the GC will NOT be performed if any other caller |
122 // Must give up the lock while at a safepoint |
124 // of GC_locker::lock() still needs GC locked. |
123 MutexUnlocker munlock(JNICritical_lock); |
125 if (!is_active_internal()) { |
124 if (PrintJNIGCStalls && PrintGCDetails) { |
126 _doing_gc = true; |
125 ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 |
127 { |
126 gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked", |
128 // Must give up the lock while at a safepoint |
127 gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); |
129 MutexUnlocker munlock(JNICritical_lock); |
|
130 if (PrintJNIGCStalls && PrintGCDetails) { |
|
131 ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 |
|
132 gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked", |
|
133 gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); |
|
134 } |
|
135 Universe::heap()->collect(GCCause::_gc_locker); |
|
136 } |
128 } |
137 _doing_gc = false; |
129 Universe::heap()->collect(GCCause::_gc_locker); |
138 } |
130 } |
139 |
131 _doing_gc = false; |
140 _needs_gc = false; |
132 _needs_gc = false; |
141 JNICritical_lock->notify_all(); |
133 JNICritical_lock->notify_all(); |
142 } |
134 } |
143 } |
135 } |
144 |
136 |