summaryrefslogtreecommitdiff
path: root/openjdkjvmti/ti_thread.cc
diff options
context:
space:
mode:
Diffstat (limited to 'openjdkjvmti/ti_thread.cc')
-rw-r--r--openjdkjvmti/ti_thread.cc134
1 files changed, 82 insertions, 52 deletions
diff --git a/openjdkjvmti/ti_thread.cc b/openjdkjvmti/ti_thread.cc
index da1c1bccc7..907b5158c6 100644
--- a/openjdkjvmti/ti_thread.cc
+++ b/openjdkjvmti/ti_thread.cc
@@ -161,13 +161,34 @@ jvmtiError ThreadUtil::GetCurrentThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread*
}
// Get the native thread. The spec says a null object denotes the current thread.
-art::Thread* ThreadUtil::GetNativeThread(jthread thread,
- const art::ScopedObjectAccessAlreadyRunnable& soa) {
+bool ThreadUtil::GetNativeThread(jthread thread,
+ const art::ScopedObjectAccessAlreadyRunnable& soa,
+ /*out*/ art::Thread** thr,
+ /*out*/ jvmtiError* err) {
if (thread == nullptr) {
- return art::Thread::Current();
+ *thr = art::Thread::Current();
+ return true;
+ } else if (!soa.Env()->IsInstanceOf(thread, art::WellKnownClasses::java_lang_Thread)) {
+ *err = ERR(INVALID_THREAD);
+ return false;
+ } else {
+ *thr = art::Thread::FromManagedThread(soa, thread);
+ return true;
}
+}
- return art::Thread::FromManagedThread(soa, thread);
+bool ThreadUtil::GetAliveNativeThread(jthread thread,
+ const art::ScopedObjectAccessAlreadyRunnable& soa,
+ /*out*/ art::Thread** thr,
+ /*out*/ jvmtiError* err) {
+ if (!GetNativeThread(thread, soa, thr, err)) {
+ return false;
+ } else if (*thr == nullptr || (*thr)->GetState() == art::ThreadState::kTerminated) {
+ *err = ERR(THREAD_NOT_ALIVE);
+ return false;
+ } else {
+ return true;
+ }
}
jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadInfo* info_ptr) {
@@ -182,9 +203,10 @@ jvmtiError ThreadUtil::GetThreadInfo(jvmtiEnv* env, jthread thread, jvmtiThreadI
art::ScopedObjectAccess soa(self);
art::MutexLock mu(self, *art::Locks::thread_list_lock_);
- art::Thread* target = GetNativeThread(thread, soa);
- if (target == nullptr && thread == nullptr) {
- return ERR(INVALID_THREAD);
+ art::Thread* target;
+ jvmtiError err = ERR(INTERNAL);
+ if (!GetNativeThread(thread, soa, &target, &err)) {
+ return err;
}
JvmtiUniquePtr<char[]> name_uptr;
@@ -297,25 +319,18 @@ struct InternalThreadState {
};
// Return the thread's (or current thread, if null) thread state.
-static InternalThreadState GetNativeThreadState(jthread thread,
- const art::ScopedObjectAccessAlreadyRunnable& soa)
+static InternalThreadState GetNativeThreadState(art::Thread* target)
REQUIRES_SHARED(art::Locks::mutator_lock_)
REQUIRES(art::Locks::thread_list_lock_, art::Locks::user_code_suspension_lock_) {
- art::Thread* self = nullptr;
- if (thread == nullptr) {
- self = art::Thread::Current();
- } else {
- self = art::Thread::FromManagedThread(soa, thread);
- }
InternalThreadState thread_state = {};
- art::MutexLock tscl_mu(soa.Self(), *art::Locks::thread_suspend_count_lock_);
- thread_state.native_thread = self;
- if (self == nullptr || self->IsStillStarting()) {
+ art::MutexLock tscl_mu(art::Thread::Current(), *art::Locks::thread_suspend_count_lock_);
+ thread_state.native_thread = target;
+ if (target == nullptr || target->IsStillStarting()) {
thread_state.art_state = art::ThreadState::kStarting;
thread_state.thread_user_code_suspend_count = 0;
} else {
- thread_state.art_state = self->GetState();
- thread_state.thread_user_code_suspend_count = self->GetUserCodeSuspendCount();
+ thread_state.art_state = target->GetState();
+ thread_state.thread_user_code_suspend_count = target->GetUserCodeSuspendCount();
}
return thread_state;
}
@@ -456,7 +471,12 @@ jvmtiError ThreadUtil::GetThreadState(jvmtiEnv* env ATTRIBUTE_UNUSED,
}
art::ScopedObjectAccess soa(self);
art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
- state = GetNativeThreadState(thread, soa);
+ jvmtiError err = ERR(INTERNAL);
+ art::Thread* target = nullptr;
+ if (!GetNativeThread(thread, soa, &target, &err)) {
+ return err;
+ }
+ state = GetNativeThreadState(target);
if (state.art_state == art::ThreadState::kStarting) {
break;
}
@@ -578,12 +598,10 @@ jvmtiError ThreadUtil::SetThreadLocalStorage(jvmtiEnv* env, jthread thread, cons
art::Thread* self = art::Thread::Current();
art::ScopedObjectAccess soa(self);
art::MutexLock mu(self, *art::Locks::thread_list_lock_);
- art::Thread* target = GetNativeThread(thread, soa);
- if (target == nullptr && thread == nullptr) {
- return ERR(INVALID_THREAD);
- }
- if (target == nullptr) {
- return ERR(THREAD_NOT_ALIVE);
+ art::Thread* target = nullptr;
+ jvmtiError err = ERR(INTERNAL);
+ if (!GetAliveNativeThread(thread, soa, &target, &err)) {
+ return err;
}
JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
@@ -607,12 +625,10 @@ jvmtiError ThreadUtil::GetThreadLocalStorage(jvmtiEnv* env,
art::Thread* self = art::Thread::Current();
art::ScopedObjectAccess soa(self);
art::MutexLock mu(self, *art::Locks::thread_list_lock_);
- art::Thread* target = GetNativeThread(thread, soa);
- if (target == nullptr && thread == nullptr) {
- return ERR(INVALID_THREAD);
- }
- if (target == nullptr) {
- return ERR(THREAD_NOT_ALIVE);
+ art::Thread* target = nullptr;
+ jvmtiError err = ERR(INTERNAL);
+ if (!GetAliveNativeThread(thread, soa, &target, &err)) {
+ return err;
}
JvmtiGlobalTLSData* global_tls = reinterpret_cast<JvmtiGlobalTLSData*>(target->GetCustomTLS());
@@ -731,9 +747,13 @@ jvmtiError ThreadUtil::SuspendOther(art::Thread* self,
{
art::ScopedObjectAccess soa(self);
art::MutexLock thread_list_mu(self, *art::Locks::thread_list_lock_);
- art::Thread* target = GetNativeThread(target_jthread, soa);
+ art::Thread* target = nullptr;
+ jvmtiError err = ERR(INTERNAL);
+ if (!GetAliveNativeThread(target_jthread, soa, &target, &err)) {
+ return err;
+ }
art::ThreadState state = target->GetState();
- if (state == art::ThreadState::kTerminated || state == art::ThreadState::kStarting) {
+ if (state == art::ThreadState::kStarting || target->IsStillStarting()) {
return ERR(THREAD_NOT_ALIVE);
} else {
art::MutexLock thread_suspend_count_mu(self, *art::Locks::thread_suspend_count_lock_);
@@ -789,9 +809,10 @@ jvmtiError ThreadUtil::SuspendThread(jvmtiEnv* env ATTRIBUTE_UNUSED, jthread thr
{
art::ScopedObjectAccess soa(self);
art::MutexLock mu(self, *art::Locks::thread_list_lock_);
- art::Thread* target = GetNativeThread(thread, soa);
- if (target == nullptr) {
- return ERR(INVALID_THREAD);
+ art::Thread* target = nullptr;
+ jvmtiError err = ERR(INTERNAL);
+ if (!GetAliveNativeThread(thread, soa, &target, &err)) {
+ return err;
} else if (target == self) {
target_is_self = true;
}
@@ -825,16 +846,14 @@ jvmtiError ThreadUtil::ResumeThread(jvmtiEnv* env ATTRIBUTE_UNUSED,
// have the 'suspend_lock' locked here.
art::ScopedObjectAccess soa(self);
art::MutexLock tll_mu(self, *art::Locks::thread_list_lock_);
- target = GetNativeThread(thread, soa);
- if (target == nullptr) {
- return ERR(INVALID_THREAD);
+ jvmtiError err = ERR(INTERNAL);
+ if (!GetAliveNativeThread(thread, soa, &target, &err)) {
+ return err;
} else if (target == self) {
// We would have paused until we aren't suspended anymore due to the ScopedObjectAccess so
// we can just return THREAD_NOT_SUSPENDED. Unfortunately we cannot do any real DCHECKs
// about current state since it's all concurrent.
return ERR(THREAD_NOT_SUSPENDED);
- } else if (target->GetState() == art::ThreadState::kTerminated) {
- return ERR(THREAD_NOT_ALIVE);
}
// The JVMTI spec requires us to return THREAD_NOT_SUSPENDED if it is alive but we really
// cannot tell why resume failed.
@@ -859,6 +878,22 @@ jvmtiError ThreadUtil::ResumeThread(jvmtiEnv* env ATTRIBUTE_UNUSED,
} while (true);
}
+static bool IsCurrentThread(jthread thr) {
+ if (thr == nullptr) {
+ return true;
+ }
+ art::Thread* self = art::Thread::Current();
+ art::ScopedObjectAccess soa(self);
+ art::MutexLock mu(self, *art::Locks::thread_list_lock_);
+ art::Thread* target = nullptr;
+ jvmtiError err_unused = ERR(INTERNAL);
+ if (ThreadUtil::GetNativeThread(thr, soa, &target, &err_unused)) {
+ return target == self;
+ } else {
+ return false;
+ }
+}
+
// Suspends all the threads in the list at the same time. Getting this behavior is a little tricky
// since we can have threads in the list multiple times. This generally doesn't matter unless the
// current thread is present multiple times. In that case we need to suspend only once and either
@@ -878,17 +913,12 @@ jvmtiError ThreadUtil::SuspendThreadList(jvmtiEnv* env,
// running thread. These indexes we need to handle specially since we need to only actually
// suspend a single time.
std::vector<jint> current_thread_indexes;
- art::Thread* self = art::Thread::Current();
for (jint i = 0; i < request_count; i++) {
- {
- art::ScopedObjectAccess soa(self);
- art::MutexLock mu(self, *art::Locks::thread_list_lock_);
- if (threads[i] == nullptr || GetNativeThread(threads[i], soa) == self) {
- current_thread_indexes.push_back(i);
- continue;
- }
+ if (IsCurrentThread(threads[i])) {
+ current_thread_indexes.push_back(i);
+ } else {
+ results[i] = env->SuspendThread(threads[i]);
}
- results[i] = env->SuspendThread(threads[i]);
}
if (!current_thread_indexes.empty()) {
jint first_current_thread_index = current_thread_indexes[0];