1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "jni.h"
18 #include "jvmti.h"
19 
20 #include <vector>
21 
22 #include "jvmti_helper.h"
23 #include "test_env.h"
24 
25 namespace art {
26 namespace common_suspension {
27 
Java_art_Suspension_isSuspended(JNIEnv * env,jclass,jthread thr)28 extern "C" JNIEXPORT jboolean JNICALL Java_art_Suspension_isSuspended(
29     JNIEnv* env, jclass, jthread thr) {
30   jint state;
31   if (JvmtiErrorToException(env, jvmti_env, jvmti_env->GetThreadState(thr, &state))) {
32     return false;
33   }
34   return (state & JVMTI_THREAD_STATE_SUSPENDED) != 0;
35 }
36 
CopyToVector(JNIEnv * env,jobjectArray thrs)37 static std::vector<jthread> CopyToVector(JNIEnv* env, jobjectArray thrs) {
38   jsize len = env->GetArrayLength(thrs);
39   std::vector<jthread> ret;
40   for (jsize i = 0; i < len; i++) {
41     ret.push_back(reinterpret_cast<jthread>(env->GetObjectArrayElement(thrs, i)));
42   }
43   return ret;
44 }
45 
Java_art_Suspension_resumeList(JNIEnv * env,jclass,jobjectArray thr)46 extern "C" JNIEXPORT jintArray JNICALL Java_art_Suspension_resumeList(JNIEnv* env,
47                                                                       jclass,
48                                                                       jobjectArray thr) {
49   static_assert(sizeof(jvmtiError) == sizeof(jint), "cannot use jintArray as jvmtiError array");
50   std::vector<jthread> threads(CopyToVector(env, thr));
51   if (env->ExceptionCheck()) {
52     return nullptr;
53   }
54   jintArray ret = env->NewIntArray(threads.size());
55   if (env->ExceptionCheck()) {
56     return nullptr;
57   }
58   jint* elems = env->GetIntArrayElements(ret, nullptr);
59   JvmtiErrorToException(env, jvmti_env,
60                         jvmti_env->ResumeThreadList(threads.size(),
61                                                     threads.data(),
62                                                     reinterpret_cast<jvmtiError*>(elems)));
63   env->ReleaseIntArrayElements(ret, elems, 0);
64   return ret;
65 }
66 
Java_art_Suspension_suspendList(JNIEnv * env,jclass,jobjectArray thrs)67 extern "C" JNIEXPORT jintArray JNICALL Java_art_Suspension_suspendList(JNIEnv* env,
68                                                                        jclass,
69                                                                        jobjectArray thrs) {
70   static_assert(sizeof(jvmtiError) == sizeof(jint), "cannot use jintArray as jvmtiError array");
71   std::vector<jthread> threads(CopyToVector(env, thrs));
72   if (env->ExceptionCheck()) {
73     return nullptr;
74   }
75   jintArray ret = env->NewIntArray(threads.size());
76   if (env->ExceptionCheck()) {
77     return nullptr;
78   }
79   jint* elems = env->GetIntArrayElements(ret, nullptr);
80   JvmtiErrorToException(env, jvmti_env,
81                         jvmti_env->SuspendThreadList(threads.size(),
82                                                      threads.data(),
83                                                      reinterpret_cast<jvmtiError*>(elems)));
84   env->ReleaseIntArrayElements(ret, elems, 0);
85   return ret;
86 }
87 
Java_art_Suspension_resume(JNIEnv * env,jclass,jthread thr)88 extern "C" JNIEXPORT void JNICALL Java_art_Suspension_resume(JNIEnv* env, jclass, jthread thr) {
89   JvmtiErrorToException(env, jvmti_env, jvmti_env->ResumeThread(thr));
90 }
91 
Java_art_Suspension_suspend(JNIEnv * env,jclass,jthread thr)92 extern "C" JNIEXPORT void JNICALL Java_art_Suspension_suspend(JNIEnv* env, jclass, jthread thr) {
93   JvmtiErrorToException(env, jvmti_env, jvmti_env->SuspendThread(thr));
94 }
95 
96 }  // namespace common_suspension
97 }  // namespace art
98 
99