24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
26 #include "gc/shared/collectedHeap.hpp" |
26 #include "gc/shared/collectedHeap.hpp" |
27 #include "gc/shared/gcLocker.inline.hpp" |
27 #include "gc/shared/gcLocker.inline.hpp" |
28 #include "memory/resourceArea.hpp" |
28 #include "memory/resourceArea.hpp" |
|
29 #include "logging/log.hpp" |
29 #include "runtime/atomic.inline.hpp" |
30 #include "runtime/atomic.inline.hpp" |
30 #include "runtime/thread.inline.hpp" |
31 #include "runtime/thread.inline.hpp" |
31 |
32 |
32 volatile jint GC_locker::_jni_lock_count = 0; |
33 volatile jint GC_locker::_jni_lock_count = 0; |
33 volatile bool GC_locker::_needs_gc = false; |
34 volatile bool GC_locker::_needs_gc = false; |
71 assert(_debug_jni_lock_count > 0, "bad value"); |
72 assert(_debug_jni_lock_count > 0, "bad value"); |
72 Atomic::dec(&_debug_jni_lock_count); |
73 Atomic::dec(&_debug_jni_lock_count); |
73 } |
74 } |
74 #endif |
75 #endif |
75 |
76 |
|
77 void GC_locker::log_debug_jni(const char* msg) { |
|
78 LogHandle(gc, jni) log; |
|
79 if (log.is_debug()) { |
|
80 ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 |
|
81 log.debug("%s Thread \"%s\" %d locked.", msg, Thread::current()->name(), _jni_lock_count); |
|
82 } |
|
83 } |
|
84 |
76 bool GC_locker::check_active_before_gc() { |
85 bool GC_locker::check_active_before_gc() { |
77 assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); |
86 assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); |
78 if (is_active() && !_needs_gc) { |
87 if (is_active() && !_needs_gc) { |
79 verify_critical_count(); |
88 verify_critical_count(); |
80 _needs_gc = true; |
89 _needs_gc = true; |
81 if (PrintJNIGCStalls && PrintGCDetails) { |
90 log_debug_jni("Setting _needs_gc."); |
82 ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 |
|
83 gclog_or_tty->print_cr("%.3f: Setting _needs_gc. Thread \"%s\" %d locked.", |
|
84 gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); |
|
85 } |
|
86 |
|
87 } |
91 } |
88 return is_active(); |
92 return is_active(); |
89 } |
93 } |
90 |
94 |
91 void GC_locker::stall_until_clear() { |
95 void GC_locker::stall_until_clear() { |
92 assert(!JavaThread::current()->in_critical(), "Would deadlock"); |
96 assert(!JavaThread::current()->in_critical(), "Would deadlock"); |
93 MutexLocker ml(JNICritical_lock); |
97 MutexLocker ml(JNICritical_lock); |
94 |
98 |
95 if (needs_gc()) { |
99 if (needs_gc()) { |
96 if (PrintJNIGCStalls && PrintGCDetails) { |
100 log_debug_jni("Allocation failed. Thread stalled by JNI critical section."); |
97 ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 |
|
98 gclog_or_tty->print_cr("%.3f: Allocation failed. Thread \"%s\" is stalled by JNI critical section, %d locked.", |
|
99 gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); |
|
100 } |
|
101 } |
101 } |
102 |
102 |
103 // Wait for _needs_gc to be cleared |
103 // Wait for _needs_gc to be cleared |
104 while (needs_gc()) { |
104 while (needs_gc()) { |
105 JNICritical_lock->wait(); |
105 JNICritical_lock->wait(); |
132 // We're the last thread out. Cause a GC to occur. |
132 // We're the last thread out. Cause a GC to occur. |
133 _doing_gc = true; |
133 _doing_gc = true; |
134 { |
134 { |
135 // Must give up the lock while at a safepoint |
135 // Must give up the lock while at a safepoint |
136 MutexUnlocker munlock(JNICritical_lock); |
136 MutexUnlocker munlock(JNICritical_lock); |
137 if (PrintJNIGCStalls && PrintGCDetails) { |
137 log_debug_jni("Performing GC after exiting critical section."); |
138 ResourceMark rm; // JavaThread::name() allocates to convert to UTF8 |
|
139 gclog_or_tty->print_cr("%.3f: Thread \"%s\" is performing GC after exiting critical section, %d locked", |
|
140 gclog_or_tty->time_stamp().seconds(), Thread::current()->name(), _jni_lock_count); |
|
141 } |
|
142 Universe::heap()->collect(GCCause::_gc_locker); |
138 Universe::heap()->collect(GCCause::_gc_locker); |
143 } |
139 } |
144 _doing_gc = false; |
140 _doing_gc = false; |
145 _needs_gc = false; |
141 _needs_gc = false; |
146 JNICritical_lock->notify_all(); |
142 JNICritical_lock->notify_all(); |