diff options
Diffstat (limited to 'openjdkjvmti/events.cc')
-rw-r--r-- | openjdkjvmti/events.cc | 88 |
1 files changed, 49 insertions, 39 deletions
diff --git a/openjdkjvmti/events.cc b/openjdkjvmti/events.cc index 4f978444f8..beb864be23 100644 --- a/openjdkjvmti/events.cc +++ b/openjdkjvmti/events.cc @@ -59,7 +59,6 @@ #include "thread-inl.h" #include "thread_list.h" #include "ti_phase.h" -#include "ti_thread.h" #include "well_known_classes.h" namespace openjdkjvmti { @@ -1275,48 +1274,59 @@ jvmtiError EventHandler::SetEvent(ArtJvmTiEnv* env, art::Thread* self = art::Thread::Current(); art::Thread* target = nullptr; - ScopedNoUserCodeSuspension snucs(self); - - bool old_state; - bool new_state; - { - // From now on we know we cannot get suspended by user-code. - // NB This does a SuspendCheck (during thread state change) so we need to - // make sure we don't have the 'suspend_lock' locked here. - art::ScopedObjectAccess soa(self); - art::WriterMutexLock el_mu(self, envs_lock_); - art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_); - jvmtiError err = ERR(INTERNAL); - if (thread != nullptr) { - if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { - return err; - } else if (target->IsStillStarting() || - target->GetState() == art::ThreadState::kStarting) { - target->Dump(LOG_STREAM(WARNING) << "Is not alive: "); - return ERR(THREAD_NOT_ALIVE); - } + do { + ThreadUtil::SuspendCheck(self); + art::MutexLock ucsl_mu(self, *art::Locks::user_code_suspension_lock_); + // Make sure we won't be suspended in the middle of holding the + // thread_suspend_count_lock_ by a user-code suspension. We retry and do + // another SuspendCheck to clear this. + if (ThreadUtil::WouldSuspendForUserCodeLocked(self)) { + continue; } + bool old_state; + bool new_state; + { + // From now on we know we cannot get suspended by user-code. + // NB This does a SuspendCheck (during thread state change) so we need to + // make sure we don't have the 'suspend_lock' locked here. + art::ScopedObjectAccess soa(self); + art::WriterMutexLock el_mu(self, envs_lock_); + art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_); + jvmtiError err = ERR(INTERNAL); + if (thread != nullptr) { + if (!ThreadUtil::GetAliveNativeThread(thread, soa, &target, &err)) { + return err; + } else if (target->IsStillStarting() || + target->GetState() == art::ThreadState::kStarting) { + target->Dump(LOG_STREAM(WARNING) << "Is not alive: "); + return ERR(THREAD_NOT_ALIVE); + } + } - art::WriterMutexLock ei_mu(self, env->event_info_mutex_); - old_state = global_mask.Test(event); - if (mode == JVMTI_ENABLE) { - env->event_masks.EnableEvent(env, target, event); - global_mask.Set(event); - new_state = true; - } else { - DCHECK_EQ(mode, JVMTI_DISABLE); - env->event_masks.DisableEvent(env, target, event); - RecalculateGlobalEventMaskLocked(event); - new_state = global_mask.Test(event); + { + art::WriterMutexLock ei_mu(self, env->event_info_mutex_); + old_state = global_mask.Test(event); + if (mode == JVMTI_ENABLE) { + env->event_masks.EnableEvent(env, target, event); + global_mask.Set(event); + new_state = true; + } else { + DCHECK_EQ(mode, JVMTI_DISABLE); + + env->event_masks.DisableEvent(env, target, event); + RecalculateGlobalEventMaskLocked(event); + new_state = global_mask.Test(event); + } + } } - } - // Handle any special work required for the event type. We still have the - // user_code_suspend_count_lock_ so there won't be any interleaving here. - if (new_state != old_state) { - return HandleEventType(event, thread, mode == JVMTI_ENABLE); - } - return OK; + // Handle any special work required for the event type. We still have the + // user_code_suspend_count_lock_ so there won't be any interleaving here. + if (new_state != old_state) { + return HandleEventType(event, thread, mode == JVMTI_ENABLE); + } + return OK; + } while (true); } void EventHandler::HandleBreakpointEventsChanged(bool added) { |