--- a/hotspot/src/share/vm/runtime/safepoint.cpp Wed Feb 01 07:59:01 2012 -0800
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp Wed Feb 01 16:57:08 2012 -0800
@@ -136,7 +136,6 @@
RuntimeService::record_safepoint_begin();
- {
MutexLocker mu(Safepoint_lock);
// Reset the count of active JNI critical threads
@@ -399,7 +398,6 @@
// Record how much time spend on the above cleanup tasks
update_statistics_on_cleanup_end(os::javaTimeNanos());
}
- }
}
// Wake up all threads, so they are ready to resume execution after the safepoint
@@ -546,6 +544,42 @@
}
+// See if the thread is running inside a lazy critical native and
+// update the thread critical count if so. Also set a suspend flag to
+// cause the native wrapper to return into the JVM to do the unlock
+// once the native finishes.
+void SafepointSynchronize::check_for_lazy_critical_native(JavaThread *thread, JavaThreadState state) {
+ if (state == _thread_in_native &&
+ thread->has_last_Java_frame() &&
+ thread->frame_anchor()->walkable()) {
+ // This thread might be in a critical native nmethod so look at
+ // the top of the stack and increment the critical count if it
+ // is.
+ frame wrapper_frame = thread->last_frame();
+ CodeBlob* stub_cb = wrapper_frame.cb();
+ if (stub_cb != NULL &&
+ stub_cb->is_nmethod() &&
+ stub_cb->as_nmethod_or_null()->is_lazy_critical_native()) {
+ // A thread could potentially be in a critical native across
+ // more than one safepoint, so only update the critical state on
+ // the first one. When it returns it will perform the unlock.
+ if (!thread->do_critical_native_unlock()) {
+#ifdef ASSERT
+ if (!thread->in_critical()) {
+ GC_locker::increment_debug_jni_lock_count();
+ }
+#endif
+ thread->enter_critical();
+ // Make sure the native wrapper calls back on return to
+ // perform the needed critical unlock.
+ thread->set_critical_native_unlock();
+ }
+ }
+ }
+}
+
+
+
// -------------------------------------------------------------------------------------------------------
// Implementation of Safepoint callback point
@@ -874,6 +908,7 @@
// agree and update the safepoint state here.
if (SafepointSynchronize::safepoint_safe(_thread, state)) {
roll_forward(_at_safepoint);
+ SafepointSynchronize::check_for_lazy_critical_native(_thread, state);
if (_thread->in_critical()) {
// Notice that this thread is in a critical section
SafepointSynchronize::increment_jni_active_count();