< prev index next >

src/hotspot/share/runtime/thread.cpp

Print this page

        

*** 2262,2284 **** "must have handled the async condition, if no exception"); } void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) { // ! // Check for pending external suspend. // If JNIEnv proxies are allowed, don't self-suspend if the target // thread is not the current thread. In older versions of jdbx, jdbx // threads could call into the VM with another thread's JNIEnv so we // can be here operating on behalf of a suspended thread (4432884). bool do_self_suspend = is_external_suspend_with_lock(); if (do_self_suspend && (!AllowJNIEnvProxy || this == JavaThread::current())) { frame_anchor()->make_walkable(this); ! java_suspend_self_with_safepoint_check(); ! } // We might be here for reasons in addition to the self-suspend request // so check for other async requests. if (check_asyncs) { check_and_handle_async_exceptions(); } JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);) --- 2262,2313 ---- "must have handled the async condition, if no exception"); } void JavaThread::handle_special_runtime_exit_condition(bool check_asyncs) { // ! // Check for pending external suspend. Internal suspend requests do ! // not use handle_special_runtime_exit_condition(). // If JNIEnv proxies are allowed, don't self-suspend if the target // thread is not the current thread. In older versions of jdbx, jdbx // threads could call into the VM with another thread's JNIEnv so we // can be here operating on behalf of a suspended thread (4432884). bool do_self_suspend = is_external_suspend_with_lock(); if (do_self_suspend && (!AllowJNIEnvProxy || this == JavaThread::current())) { + // + // Because thread is external suspended the safepoint code will count + // thread as at a safepoint. This can be odd because we can be here + // as _thread_in_Java which would normally transition to _thread_blocked + // at a safepoint. We would like to mark the thread as _thread_blocked + // before calling java_suspend_self like all other callers of it but + // we must then observe proper safepoint protocol. (We can't leave + // _thread_blocked with a safepoint in progress). However we can be + // here as _thread_in_native_trans so we can't use a normal transition + // constructor/destructor pair because they assert on that type of + // transition. We could do something like: + // + // JavaThreadState state = thread_state(); + // set_thread_state(_thread_in_vm); + // { + // ThreadBlockInVM tbivm(this); + // java_suspend_self() + // } + // set_thread_state(_thread_in_vm_trans); + // if (safepoint) block; + // set_thread_state(state); + // + // but that is pretty messy. Instead we just go with the way the + // code has worked before and note that this is the only path to + // java_suspend_self that doesn't put the thread in _thread_blocked + // mode. + frame_anchor()->make_walkable(this); ! java_suspend_self(); // We might be here for reasons in addition to the self-suspend request // so check for other async requests. + } + if (check_asyncs) { check_and_handle_async_exceptions(); } JFR_ONLY(SUSPEND_THREAD_CONDITIONAL(this);)
*** 2393,2403 **** // thread. java_suspend_self() is the second stage of cooperative // suspension for external suspend requests and should only be used // to complete an external suspend request. // int JavaThread::java_suspend_self() { - assert(thread_state() == _thread_blocked, "wrong state for java_suspend_self()"); int ret = 0; // we are in the process of exiting so don't suspend if (is_exiting()) { clear_external_suspend(); --- 2422,2431 ----
*** 2441,2471 **** } return ret; } - // Helper routine to set up the correct thread state before calling java_suspend_self. - // This is called when regular thread-state transition helpers can't be used because - // we can be in various states, in particular _thread_in_native_trans. - // Because this thread is external suspended the safepoint code will count it as at - // a safepoint, regardless of what its actual current thread-state is. But - // is_ext_suspend_completed() may be waiting to see a thread transition from - // _thread_in_native_trans to _thread_blocked. So we set the thread state directly - // to _thread_blocked. The problem with setting thread state directly is that a - // safepoint could happen just after java_suspend_self() returns after being resumed, - // and the VM thread will see the _thread_blocked state. So we must check for a safepoint - // after restoring the state to make sure we won't leave while a safepoint is in progress. - void JavaThread::java_suspend_self_with_safepoint_check() { - assert(this == Thread::current(), "invariant"); - JavaThreadState state = thread_state(); - set_thread_state(_thread_blocked); - java_suspend_self(); - set_thread_state(state); - InterfaceSupport::serialize_thread_state_with_handler(this); - SafepointMechanism::block_if_requested(this); - } - #ifdef ASSERT // Verify the JavaThread has not yet been published in the Threads::list, and // hence doesn't need protection from concurrent access at this stage. void JavaThread::verify_not_published() { // Cannot create a ThreadsListHandle here and check !tlh.includes(this) --- 2469,2478 ----
*** 2493,2507 **** // If JNIEnv proxies are allowed, don't self-suspend if the target // thread is not the current thread. In older versions of jdbx, jdbx // threads could call into the VM with another thread's JNIEnv so we // can be here operating on behalf of a suspended thread (4432884). if (do_self_suspend && (!AllowJNIEnvProxy || curJT == thread)) { ! thread->java_suspend_self_with_safepoint_check(); ! } else { ! SafepointMechanism::block_if_requested(curJT); } if (thread->is_deopt_suspend()) { thread->clear_deopt_suspend(); RegisterMap map(thread, false); frame f = thread->last_frame(); while (f.id() != thread->must_deopt_id() && ! f.is_first_frame()) { --- 2500,2536 ---- // If JNIEnv proxies are allowed, don't self-suspend if the target // thread is not the current thread. In older versions of jdbx, jdbx // threads could call into the VM with another thread's JNIEnv so we // can be here operating on behalf of a suspended thread (4432884). if (do_self_suspend && (!AllowJNIEnvProxy || curJT == thread)) { ! JavaThreadState state = thread->thread_state(); ! ! // We mark this thread_blocked state as a suspend-equivalent so ! // that a caller to is_ext_suspend_completed() won't be confused. ! // The suspend-equivalent state is cleared by java_suspend_self(). ! thread->set_suspend_equivalent(); ! ! // If the safepoint code sees the _thread_in_native_trans state, it will ! // wait until the thread changes to other thread state. There is no ! // guarantee on how soon we can obtain the SR_lock and complete the ! // self-suspend request. It would be a bad idea to let safepoint wait for ! // too long. Temporarily change the state to _thread_blocked to ! // let the VM thread know that this thread is ready for GC. The problem ! // of changing thread state is that safepoint could happen just after ! // java_suspend_self() returns after being resumed, and VM thread will ! // see the _thread_blocked state. We must check for safepoint ! // after restoring the state and make sure we won't leave while a safepoint ! // is in progress. ! thread->set_thread_state(_thread_blocked); ! thread->java_suspend_self(); ! thread->set_thread_state(state); ! ! InterfaceSupport::serialize_thread_state_with_handler(thread); } + SafepointMechanism::block_if_requested(curJT); + if (thread->is_deopt_suspend()) { thread->clear_deopt_suspend(); RegisterMap map(thread, false); frame f = thread->last_frame(); while (f.id() != thread->must_deopt_id() && ! f.is_first_frame()) {
< prev index next >