Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/SuspendWithCurrentThread/libSuspendWithCurrentThread.cpp
41155 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223#include <string.h>24#include <atomic>25#include "jvmti.h"2627extern "C" {2829static jvmtiEnv* jvmti = NULL;30static jthread* threads = NULL;31static jsize threads_count = 0;32static std::atomic<bool> is_exited_from_suspend;3334#define LOG(...) \35do { \36printf(__VA_ARGS__); \37printf("\n"); \38fflush(stdout); \39} while (0)4041static void42check_jvmti_status(JNIEnv* jni, jvmtiError err, const char* msg) {43if (err != JVMTI_ERROR_NONE) {44LOG("check_jvmti_status: JVMTI function returned error: %d", err);45jni->FatalError(msg);46}47}4849JNIEXPORT void JNICALL50Java_SuspendWithCurrentThread_registerTestedThreads(JNIEnv *jni, jclass cls, jobjectArray threadsArr) {51LOG("\nregisterTestedThreads: started");52threads_count = jni->GetArrayLength(threadsArr);5354jvmtiError err = jvmti->Allocate((threads_count * sizeof(jthread)),55(unsigned char**)&threads);56check_jvmti_status(jni, err, "registerTestedThreads: error in JVMTI Allocate threads array");5758for (int i = 0; i < threads_count; i++) {59jobject elem = jni->GetObjectArrayElement(threadsArr, i);60threads[i] = (jthread)jni->NewGlobalRef(elem);61}62LOG("registerTestedThreads: finished\n");63}6465/* This function is executed on the suspender thread which is not Main thread */66JNIEXPORT void JNICALL67Java_ThreadToSuspend_suspendTestedThreads(JNIEnv *jni, jclass cls) {68jvmtiError* results = NULL;69jvmtiError err;7071LOG("\nsuspendTestedThreads: started");72err = jvmti->Allocate((threads_count * sizeof(jvmtiError)),73(unsigned char**)&results);74check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI Allocate results array");7576LOG("suspendTestedThreads: before JVMTI SuspendThreadList");77err = jvmti->SuspendThreadList(threads_count, threads, results);78is_exited_from_suspend.store(true);79check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI SuspendThreadList");8081LOG("suspendTestedThreads: check and print SuspendThreadList results:");82for (int i = 0; i < threads_count; i++) {83LOG(" thread #%d: (%d)", i, (int)results[i]);84check_jvmti_status(jni, results[i], "suspendTestedThreads: error in SuspendThreadList results[i]");85}86LOG("suspendTestedThreads: finished\n");8788err = jvmti->Deallocate((unsigned char*)results);89check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI Deallocate results");90}9192JNIEXPORT jboolean JNICALL93Java_SuspendWithCurrentThread_checkTestedThreadsSuspended(JNIEnv *jni, jclass cls) {94LOG("checkTestedThreadsSuspended: started");9596for (int i = 0; i < threads_count; i++) {97jint state = 0;98jvmtiError err = jvmti->GetThreadState(threads[i], &state);99check_jvmti_status(jni, err, "checkTestedThreadsSuspended: error in GetThreadState");100101if ((state & JVMTI_THREAD_STATE_SUSPENDED) == 0) {102LOG("thread #%d has not been suspended yet: "103"# state: (%#x)", i, (int)state);104return JNI_FALSE;105}106}107if (is_exited_from_suspend.load()) {108LOG("Thread didn't stop in self suspend.");109return JNI_FALSE;110}111LOG("checkTestedThreadsSuspended: finished\n");112return JNI_TRUE;113}114115JNIEXPORT void JNICALL116Java_SuspendWithCurrentThread_resumeTestedThreads(JNIEnv *jni, jclass cls) {117jvmtiError* results = NULL;118jvmtiError err;119120LOG("\nresumeTestedThreads: started");121err = jvmti->Allocate((threads_count * sizeof(jvmtiError)),122(unsigned char**)&results);123check_jvmti_status(jni, err, "resumeTestedThreads: error in JVMTI Allocate results array");124125LOG("resumeTestedThreads: before JVMTI ResumeThreadList");126err = jvmti->ResumeThreadList(threads_count, threads, results);127check_jvmti_status(jni, err, "resumeTestedThreads: error in ResumeThreadList");128129LOG("resumeTestedThreads: check and print ResumeThreadList results:");130for (int i = 0; i < threads_count; i++) {131LOG(" thread #%d: (%d)", i, (int)results[i]);132check_jvmti_status(jni, results[i], "resumeTestedThreads: error in ResumeThreadList results[i]");133}134135err = jvmti->Deallocate((unsigned char*)results);136check_jvmti_status(jni, err, "resumeTestedThreads: error in JVMTI Deallocate results");137138LOG("resumeTestedThreads: finished\n");139}140141JNIEXPORT void JNICALL142Java_SuspendWithCurrentThread_releaseTestedThreadsInfo(JNIEnv *jni, jclass cls) {143jvmtiError err;144145LOG("\nreleaseTestedThreadsInfo: started");146147for (int i = 0; i < threads_count; i++) {148if (threads[i] != NULL) {149jni->DeleteGlobalRef(threads[i]);150}151}152err = jvmti->Deallocate((unsigned char*)threads);153check_jvmti_status(jni, err, "releaseTestedThreadsInfo: error in JVMTI Deallocate threads");154155LOG("releaseTestedThreadsInfo: finished\n");156}157158159/** Agent library initialization. */160161JNIEXPORT jint JNICALL162Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {163LOG("\nAgent_OnLoad started");164is_exited_from_suspend.store(false);165// create JVMTI environment166if (jvm->GetEnv((void **) (&jvmti), JVMTI_VERSION) != JNI_OK) {167return JNI_ERR;168}169170// add specific capabilities for suspending thread171jvmtiCapabilities suspendCaps;172memset(&suspendCaps, 0, sizeof(suspendCaps));173suspendCaps.can_suspend = 1;174175jvmtiError err = jvmti->AddCapabilities(&suspendCaps);176if (err != JVMTI_ERROR_NONE) {177return JNI_ERR;178}179LOG("Agent_OnLoad finished\n");180return JNI_OK;181}182183}184185186