diff options
author | 2017-11-17 16:39:01 -0800 | |
---|---|---|
committer | 2017-11-20 10:58:30 -0800 | |
commit | e5a2ae30bdbe379695dc886861b23dce57de0825 (patch) | |
tree | 41efa0e726e23607557fe7d8bbc03854cf06ea0f /openjdkjvmti/ti_phase.cc | |
parent | 8acd00f9e65078f0f9d3c6fa7fea19ee0c17567a (diff) |
Make JVMTI DisposeEnvironment and GetEnv thread safe.
Previously we were relying on the mutator lock to keep these safe but
it turns out this was not sufficient. We give the list of active
jvmtiEnv's it's own lock to synchronize access.
We also changed it so that during events we would collect all the
environments and callbacks prior to actually calling any of them.
This is required for making sure that we don't hold locks across user
code or potentially miss any environments. This does have implications
for when one is last able to prevent an environment from getting an
event but since the spec is vague about this anyway this is not an
issue. Doing this required a major re-write of our event-dispatch
system.
Test: ./test.py --host -j50
Test: ./art/tools/run-libjdwp-tests.sh --mode=host
Bug: 69465262
Change-Id: I170950db6c6e43b5f3c8bdca1b8d087937070496
Diffstat (limited to 'openjdkjvmti/ti_phase.cc')
-rw-r--r-- | openjdkjvmti/ti_phase.cc | 11 |
1 files changed, 4 insertions, 7 deletions
diff --git a/openjdkjvmti/ti_phase.cc b/openjdkjvmti/ti_phase.cc index 23df27fbda..7157974c13 100644 --- a/openjdkjvmti/ti_phase.cc +++ b/openjdkjvmti/ti_phase.cc @@ -57,6 +57,7 @@ struct PhaseUtil::PhaseCallback : public art::RuntimePhaseCallback { } void NextRuntimePhase(RuntimePhase phase) REQUIRES_SHARED(art::Locks::mutator_lock_) OVERRIDE { + art::Thread* self = art::Thread::Current(); switch (phase) { case RuntimePhase::kInitialAgents: PhaseUtil::current_phase_ = JVMTI_PHASE_PRIMORDIAL; @@ -64,8 +65,7 @@ struct PhaseUtil::PhaseCallback : public art::RuntimePhaseCallback { case RuntimePhase::kStart: { PhaseUtil::current_phase_ = JVMTI_PHASE_START; - art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative); - event_handler->DispatchEvent<ArtJvmtiEvent::kVmStart>(nullptr, GetJniEnv()); + event_handler->DispatchEvent<ArtJvmtiEvent::kVmStart>(self, GetJniEnv()); } break; case RuntimePhase::kInit: @@ -74,9 +74,7 @@ struct PhaseUtil::PhaseCallback : public art::RuntimePhaseCallback { PhaseUtil::current_phase_ = JVMTI_PHASE_LIVE; { ScopedLocalRef<jthread> thread(GetJniEnv(), GetCurrentJThread()); - art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative); - event_handler->DispatchEvent<ArtJvmtiEvent::kVmInit>( - nullptr, GetJniEnv(), thread.get()); + event_handler->DispatchEvent<ArtJvmtiEvent::kVmInit>(self, GetJniEnv(), thread.get()); } // We need to have these events be ordered to match behavior expected by some real-world // agents. The spec does not really require this but compatibility is a useful property to @@ -86,8 +84,7 @@ struct PhaseUtil::PhaseCallback : public art::RuntimePhaseCallback { break; case RuntimePhase::kDeath: { - art::ScopedThreadSuspension sts(art::Thread::Current(), art::ThreadState::kNative); - event_handler->DispatchEvent<ArtJvmtiEvent::kVmDeath>(nullptr, GetJniEnv()); + event_handler->DispatchEvent<ArtJvmtiEvent::kVmDeath>(self, GetJniEnv()); PhaseUtil::current_phase_ = JVMTI_PHASE_DEAD; } // TODO: Block events now. |