9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "gc/shared/collectedHeap.hpp"
27 #include "gc/shared/gcLocker.inline.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "runtime/atomic.inline.hpp"
30 #include "runtime/thread.inline.hpp"
31
32 volatile jint GC_locker::_jni_lock_count = 0;
33 volatile bool GC_locker::_needs_gc = false;
34 volatile bool GC_locker::_doing_gc = false;
35
36 #ifdef ASSERT
37 volatile jint GC_locker::_debug_jni_lock_count = 0;
38 #endif
39
40
41 #ifdef ASSERT
42 void GC_locker::verify_critical_count() {
43 if (SafepointSynchronize::is_at_safepoint()) {
44 assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree");
45 int count = 0;
46 // Count the number of threads with critical operations in progress
47 for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
48 if (thr->in_critical()) {
56 tty->print_cr(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());
57 }
58 }
59 }
60 assert(_jni_lock_count == count, "must be equal");
61 }
62 }
63
64 // In debug mode track the locking state at all times
65 void GC_locker::increment_debug_jni_lock_count() {
66 assert(_debug_jni_lock_count >= 0, "bad value");
67 Atomic::inc(&_debug_jni_lock_count);
68 }
69
70 void GC_locker::decrement_debug_jni_lock_count() {
71 assert(_debug_jni_lock_count > 0, "bad value");
72 Atomic::dec(&_debug_jni_lock_count);
73 }
74 #endif
75
76 bool GC_locker::check_active_before_gc() {
77 assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
78 if (is_active() && !_needs_gc) {
79 verify_critical_count();
80 _needs_gc = true;
81 if (PrintJNIGCStalls && PrintGCDetails) {
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 }
88 return is_active();
89 }
90
91 void GC_locker::stall_until_clear() {
92 assert(!JavaThread::current()->in_critical(), "Would deadlock");
93 MutexLocker ml(JNICritical_lock);
94
95 if (needs_gc()) {
96 if (PrintJNIGCStalls && PrintGCDetails) {
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 }
102
103 // Wait for _needs_gc to be cleared
104 while (needs_gc()) {
105 JNICritical_lock->wait();
106 }
107 }
108
109 void GC_locker::jni_lock(JavaThread* thread) {
110 assert(!thread->in_critical(), "shouldn't currently be in a critical region");
111 MutexLocker mu(JNICritical_lock);
112 // Block entering threads if we know at least one thread is in a
113 // JNI critical region and we need a GC.
114 // We check that at least one thread is in a critical region before
115 // blocking because blocked threads are woken up by a thread exiting
116 // a JNI critical region.
117 while (is_active_and_needs_gc() || _doing_gc) {
118 JNICritical_lock->wait();
119 }
120 thread->enter_critical();
121 _jni_lock_count++;
122 increment_debug_jni_lock_count();
123 }
124
125 void GC_locker::jni_unlock(JavaThread* thread) {
126 assert(thread->in_last_critical(), "should be exiting critical region");
127 MutexLocker mu(JNICritical_lock);
128 _jni_lock_count--;
129 decrement_debug_jni_lock_count();
130 thread->exit_critical();
131 if (needs_gc() && !is_active_internal()) {
132 // We're the last thread out. Cause a GC to occur.
133 _doing_gc = true;
134 {
135 // Must give up the lock while at a safepoint
136 MutexUnlocker munlock(JNICritical_lock);
137 if (PrintJNIGCStalls && PrintGCDetails) {
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);
143 }
144 _doing_gc = false;
145 _needs_gc = false;
146 JNICritical_lock->notify_all();
147 }
148 }
149
150 // Implementation of No_GC_Verifier
151
152 #ifdef ASSERT
153
154 No_GC_Verifier::No_GC_Verifier(bool verifygc) {
155 _verifygc = verifygc;
156 if (_verifygc) {
157 CollectedHeap* h = Universe::heap();
158 assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
159 _old_invocations = h->total_collections();
160 }
161 }
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "precompiled.hpp"
26 #include "gc/shared/collectedHeap.hpp"
27 #include "gc/shared/gcLocker.inline.hpp"
28 #include "memory/resourceArea.hpp"
29 #include "logging/log.hpp"
30 #include "runtime/atomic.inline.hpp"
31 #include "runtime/thread.inline.hpp"
32
33 volatile jint GC_locker::_jni_lock_count = 0;
34 volatile bool GC_locker::_needs_gc = false;
35 volatile bool GC_locker::_doing_gc = false;
36
37 #ifdef ASSERT
38 volatile jint GC_locker::_debug_jni_lock_count = 0;
39 #endif
40
41
42 #ifdef ASSERT
43 void GC_locker::verify_critical_count() {
44 if (SafepointSynchronize::is_at_safepoint()) {
45 assert(!needs_gc() || _debug_jni_lock_count == _jni_lock_count, "must agree");
46 int count = 0;
47 // Count the number of threads with critical operations in progress
48 for (JavaThread* thr = Threads::first(); thr; thr = thr->next()) {
49 if (thr->in_critical()) {
57 tty->print_cr(INTPTR_FORMAT " in_critical %d", p2i(thr), thr->in_critical());
58 }
59 }
60 }
61 assert(_jni_lock_count == count, "must be equal");
62 }
63 }
64
65 // In debug mode track the locking state at all times
66 void GC_locker::increment_debug_jni_lock_count() {
67 assert(_debug_jni_lock_count >= 0, "bad value");
68 Atomic::inc(&_debug_jni_lock_count);
69 }
70
71 void GC_locker::decrement_debug_jni_lock_count() {
72 assert(_debug_jni_lock_count > 0, "bad value");
73 Atomic::dec(&_debug_jni_lock_count);
74 }
75 #endif
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
85 bool GC_locker::check_active_before_gc() {
86 assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint");
87 if (is_active() && !_needs_gc) {
88 verify_critical_count();
89 _needs_gc = true;
90 log_debug_jni("Setting _needs_gc.");
91 }
92 return is_active();
93 }
94
95 void GC_locker::stall_until_clear() {
96 assert(!JavaThread::current()->in_critical(), "Would deadlock");
97 MutexLocker ml(JNICritical_lock);
98
99 if (needs_gc()) {
100 log_debug_jni("Allocation failed. Thread stalled by JNI critical section.");
101 }
102
103 // Wait for _needs_gc to be cleared
104 while (needs_gc()) {
105 JNICritical_lock->wait();
106 }
107 }
108
109 void GC_locker::jni_lock(JavaThread* thread) {
110 assert(!thread->in_critical(), "shouldn't currently be in a critical region");
111 MutexLocker mu(JNICritical_lock);
112 // Block entering threads if we know at least one thread is in a
113 // JNI critical region and we need a GC.
114 // We check that at least one thread is in a critical region before
115 // blocking because blocked threads are woken up by a thread exiting
116 // a JNI critical region.
117 while (is_active_and_needs_gc() || _doing_gc) {
118 JNICritical_lock->wait();
119 }
120 thread->enter_critical();
121 _jni_lock_count++;
122 increment_debug_jni_lock_count();
123 }
124
125 void GC_locker::jni_unlock(JavaThread* thread) {
126 assert(thread->in_last_critical(), "should be exiting critical region");
127 MutexLocker mu(JNICritical_lock);
128 _jni_lock_count--;
129 decrement_debug_jni_lock_count();
130 thread->exit_critical();
131 if (needs_gc() && !is_active_internal()) {
132 // We're the last thread out. Cause a GC to occur.
133 _doing_gc = true;
134 {
135 // Must give up the lock while at a safepoint
136 MutexUnlocker munlock(JNICritical_lock);
137 log_debug_jni("Performing GC after exiting critical section.");
138 Universe::heap()->collect(GCCause::_gc_locker);
139 }
140 _doing_gc = false;
141 _needs_gc = false;
142 JNICritical_lock->notify_all();
143 }
144 }
145
146 // Implementation of No_GC_Verifier
147
148 #ifdef ASSERT
149
150 No_GC_Verifier::No_GC_Verifier(bool verifygc) {
151 _verifygc = verifygc;
152 if (_verifygc) {
153 CollectedHeap* h = Universe::heap();
154 assert(!h->is_gc_active(), "GC active during No_GC_Verifier");
155 _old_invocations = h->total_collections();
156 }
157 }
|