Path: blob/master/test/hotspot/jtreg/vmTestbase/nsk/monitoring/share/ThreadController.cpp
40948 views
/*1* Copyright (c) 2003, 2019, 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 <assert.h>24#include <jni.h>25#include <jvmti.h>26#include <stdio.h>27#include "jni_tools.h"2829extern "C" {3031#define FIND_CLASS(_class, _className)\32if (!NSK_JNI_VERIFY(env, (_class = \33env->FindClass(_className)) != NULL))\34return3536#define GET_OBJECT_CLASS(_class, _obj)\37if (!NSK_JNI_VERIFY(env, (_class = \38env->GetObjectClass(_obj)) != NULL))\39return4041#define GET_STATIC_FIELD_ID(_fieldID, _class, _fieldName, _fieldSig)\42if (!NSK_JNI_VERIFY(env, (_fieldID = \43env->GetStaticFieldID(_class, _fieldName, _fieldSig)) != NULL))\44return4546#define GET_STATIC_OBJ_FIELD(_value, _class, _fieldName, _fieldSig)\47GET_STATIC_FIELD_ID(field, _class, _fieldName, _fieldSig);\48_value = env->GetStaticObjectField(_class, field)4950#define GET_STATIC_BOOL_FIELD(_value, _class, _fieldName)\51GET_STATIC_FIELD_ID(field, _class, _fieldName, "Z");\52_value = env->GetStaticBooleanField(_class, field)5354#define GET_FIELD_ID(_fieldID, _class, _fieldName, _fieldSig)\55if (!NSK_JNI_VERIFY(env, (_fieldID = \56env->GetFieldID(_class, _fieldName, _fieldSig)) != NULL))\57return5859#define GET_INT_FIELD(_value, _obj, _class, _fieldName)\60GET_FIELD_ID(field, _class, _fieldName, "I");\61_value = env->GetIntField(_obj, field)6263#define GET_BOOL_FIELD(_value, _obj, _class, _fieldName)\64GET_FIELD_ID(field, _class, _fieldName, "Z");\65_value = env->GetBooleanField(_obj, field)6667#define GET_LONG_FIELD(_value, _obj, _class, _fieldName)\68GET_FIELD_ID(field, _class, _fieldName, "J");\69_value = env->GetLongField(_obj, field)7071#define GET_STATIC_INT_FIELD(_value, _class, _fieldName)\72GET_STATIC_FIELD_ID(field, _class, _fieldName, "I");\73_value = env->GetStaticIntField(_class, field)7475#define SET_INT_FIELD(_obj, _class, _fieldName, _newValue)\76GET_FIELD_ID(field, _class, _fieldName, "I");\77env->SetIntField(_obj, field, _newValue)7879#define GET_OBJ_FIELD(_value, _obj, _class, _fieldName, _fieldSig)\80GET_FIELD_ID(field, _class, _fieldName, _fieldSig);\81_value = env->GetObjectField(_obj, field)828384#define GET_ARR_ELEMENT(_arr, _index)\85env->GetObjectArrayElement(_arr, _index)8687#define SET_ARR_ELEMENT(_arr, _index, _newValue)\88env->SetObjectArrayElement(_arr, _index, _newValue)8990#define GET_STATIC_METHOD_ID(_methodID, _class, _methodName, _sig)\91if (!NSK_JNI_VERIFY(env, (_methodID = \92env->GetStaticMethodID(_class, _methodName, _sig)) != NULL))\93return9495#define GET_METHOD_ID(_methodID, _class, _methodName, _sig)\96if (!NSK_JNI_VERIFY(env, (_methodID = \97env->GetMethodID(_class, _methodName, _sig)) != NULL))\98return99100#define CALL_STATIC_VOID_NOPARAM(_class, _methodName)\101GET_STATIC_METHOD_ID(method, _class, _methodName, "()V");\102if (!NSK_JNI_VERIFY_VOID(env, env->CallStaticVoidMethod(_class, method)))\103return104105#define CALL_STATIC_VOID(_class, _methodName, _sig, _param)\106GET_STATIC_METHOD_ID(method, _class, _methodName, _sig);\107if (!NSK_JNI_VERIFY_VOID(env, env->CallStaticVoidMethod(_class, method, _param)))\108return109110#define CALL_STATIC_OBJ(_value, _class, _methodName, _sig, _param)\111GET_STATIC_METHOD_ID(method, _class, _methodName, _sig);\112_value = env->CallStaticObjectMethod(_class, method, _param)113114#define CALL_VOID_NOPARAM(_obj, _class, _methodName)\115GET_METHOD_ID(method, _class, _methodName, "()V");\116if (!NSK_JNI_VERIFY_VOID(env, env->CallVoidMethod(_obj, method)))\117return118119#define CALL_VOID(_obj, _class, _methodName, _sig, _param)\120GET_METHOD_ID(method, _class, _methodName, "()V");\121if (!NSK_JNI_VERIFY_VOID(env, env->CallVoidMethod(_obj, method, _param)))\122return123124#define CALL_VOID2(_obj, _class, _methodName, _sig, _param1, _param2)\125GET_METHOD_ID(method, _class, _methodName, _sig);\126if (!NSK_JNI_VERIFY_VOID(env, env->CallVoidMethod(_obj, method, _param1, _param2)))\127return128129#define CALL_INT_NOPARAM(_value, _obj, _class, _methodName)\130GET_METHOD_ID(method, _class, _methodName, "()I");\131_value = env->CallIntMethod(_obj, method)132133#define NEW_OBJ(_obj, _class, _constructorName, _sig, _params)\134GET_METHOD_ID(method, _class, _constructorName, _sig);\135if (!NSK_JNI_VERIFY(env, (_obj = \136env->NewObject(_class, method, _params)) != NULL))\137return138139#define MONITOR_ENTER(x) \140NSK_JNI_VERIFY(env, env->MonitorEnter(x) == 0)141142#define MONITOR_EXIT(x) \143NSK_JNI_VERIFY(env, env->MonitorExit(x) == 0)144145#define TRACE(msg)\146GET_OBJ_FIELD(logger, obj, threadClass, "logger", "Lnsk/share/Log$Logger;");\147jmsg = env->NewStringUTF(msg);\148CALL_VOID2(logger, loggerClass, "trace",\149"(ILjava/lang/String;)V", 50, jmsg)150151static const char *SctrlClassName="nsk/monitoring/share/ThreadController";152static const char *SthreadControllerSig153= "Lnsk/monitoring/share/ThreadController;";154155static const char *SThreadsGroupLocksSig156="Lnsk/monitoring/share/ThreadsGroupLocks;";157static const char *SThreadsGroupLocksClassName158="nsk/monitoring/share/ThreadsGroupLocks";159160161static const char *SbringState_mn="bringState";162static const char *SnativeBringState_mn="nativeBringState";163static const char *SrecursiveMethod_mn="recursiveMethod";164static const char *SnativeRecursiveMethod_mn="nativeRecursiveMethod";165static const char *SloggerClassName = "nsk/share/Log$Logger";166167static const char *Snoparams="()V";168static const char *Slongparam="(J)V";169170/*171* Class: nsk_monitoring_share_BaseThread172* Method: nativeRecursiveMethod173* Signature: ()V174*/175JNIEXPORT void JNICALL176Java_nsk_monitoring_share_BaseThread_nativeRecursiveMethod(JNIEnv *env,177jobject obj) {178jint currDepth, maxDepth;179jobject logger;180jstring jmsg;181jfieldID field;182jmethodID method;183184jobject controller;185jclass threadClass, ctrlClass, loggerClass;186187int invocationType;188189GET_OBJECT_CLASS(threadClass, obj);190FIND_CLASS(ctrlClass, SctrlClassName);191FIND_CLASS(loggerClass, SloggerClassName);192193194/* currDepth++ */195GET_INT_FIELD(currDepth, obj, threadClass, "currentDepth");196currDepth++;197SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);198199GET_OBJ_FIELD(controller, obj, threadClass, "controller",200SthreadControllerSig);201GET_INT_FIELD(maxDepth, controller, ctrlClass, "maxDepth");202203GET_STATIC_INT_FIELD(invocationType, ctrlClass, "invocationType");204205if (maxDepth - currDepth > 0)206{207CALL_STATIC_VOID_NOPARAM(threadClass, "yield");208209if (invocationType == 2/*MIXED_TYPE*/)210{211CALL_VOID_NOPARAM(obj, threadClass, SrecursiveMethod_mn);212}213else214{215CALL_VOID_NOPARAM(obj, threadClass, SnativeRecursiveMethod_mn);216}217}218else219{220TRACE("state has been reached");221if (invocationType == 2/*MIXED_TYPE*/)222{223CALL_VOID_NOPARAM(obj, threadClass, SbringState_mn);224}225else226{227CALL_VOID_NOPARAM(obj, threadClass, SnativeBringState_mn);228}229}230231currDepth--;232GET_OBJECT_CLASS(threadClass, obj);233SET_INT_FIELD(obj, threadClass, "currentDepth", currDepth);234}235236/*237* Class: nsk_monitoring_share_BlockedThread238* Method: nativeBringState239* Signature: ()V240*/241JNIEXPORT void JNICALL242Java_nsk_monitoring_share_BlockedThread_nativeBringState(JNIEnv *env,243jobject obj) {244jobject logger;245jstring jmsg;246jfieldID field;247jmethodID method;248249jclass threadClass, loggerClass;250251jobject STATE;252253//ThreadsGroupLocks:254jclass ThreadsGroupLocks;255jobject threadsGroupLocks;256jmethodID getBarrier;257258259//CountDownLatch260jobject barrier;261jclass CountDownLatch;262263//Blocker264jobject blocker;265jclass Blocker;266267GET_OBJECT_CLASS(threadClass, obj);268269FIND_CLASS(loggerClass, SloggerClassName);270FIND_CLASS(ThreadsGroupLocks, SThreadsGroupLocksClassName);271FIND_CLASS(Blocker, "Lnsk/monitoring/share/ThreadsGroupLocks$Blocker;");272FIND_CLASS(CountDownLatch, "nsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch");273274GET_OBJ_FIELD(threadsGroupLocks, obj, threadClass, "threadsGroupLocks", SThreadsGroupLocksSig);275GET_STATIC_OBJ_FIELD(STATE, threadClass, "STATE", "Ljava/lang/Thread$State;");276GET_OBJ_FIELD(blocker, threadsGroupLocks, ThreadsGroupLocks, "blocker", "Lnsk/monitoring/share/ThreadsGroupLocks$Blocker;");277278getBarrier = env->GetMethodID(ThreadsGroupLocks, "getBarrier",279"(Ljava/lang/Thread$State;)Lnsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch;");280barrier = env->CallObjectMethod(threadsGroupLocks, getBarrier, STATE);281282283TRACE("entering to monitor");284285CALL_VOID_NOPARAM(barrier, CountDownLatch, "countDown");286CALL_VOID_NOPARAM(blocker, Blocker, "block");287TRACE("exiting from monitor");288289}290291/*292* Class: nsk_monitoring_share_WaitingThread293* Method: nativeBringState294* Signature: ()V295*/296JNIEXPORT void JNICALL297Java_nsk_monitoring_share_WaitingThread_nativeBringState(JNIEnv *env,298jobject obj) {299jobject logger;300jstring jmsg;301jfieldID field;302jmethodID method;303304jclass threadClass, loggerClass;305306//STATE307jobject STATE;308309//ThreadsGroupLocks:310jclass ThreadsGroupLocks;311jobject threadsGroupLocks;312jmethodID getBarrier;313314//CountDownLatch315jobject barrier;316jclass CountDownLatch;317318GET_OBJECT_CLASS(threadClass, obj);319320FIND_CLASS(loggerClass, SloggerClassName);321FIND_CLASS(ThreadsGroupLocks, "nsk/monitoring/share/ThreadsGroupLocks");322FIND_CLASS(CountDownLatch, "nsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch");323324GET_STATIC_OBJ_FIELD(STATE, threadClass, "STATE", "Ljava/lang/Thread$State;");325GET_OBJ_FIELD(threadsGroupLocks, obj, threadClass, "threadsGroupLocks", "Lnsk/monitoring/share/ThreadsGroupLocks;");326327getBarrier = env->GetMethodID(ThreadsGroupLocks, "getBarrier",328"(Ljava/lang/Thread$State;)Lnsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch;");329barrier = env->CallObjectMethod(threadsGroupLocks, getBarrier, STATE);330CALL_VOID_NOPARAM(barrier, CountDownLatch, "countDown");331332TRACE("waiting on a monitor");333CALL_VOID_NOPARAM(barrier, CountDownLatch, "await");334}335336/*337* Class: nsk_monitoring_share_SleepingThread338* Method: nativeBringState339* Signature: ()V340*/341JNIEXPORT void JNICALL342Java_nsk_monitoring_share_SleepingThread_nativeBringState(JNIEnv *env,343jobject obj) {344jfieldID field;345jmethodID method;346347jclass threadClass, loggerClass;348349//STATE350jobject STATE;351352//ThreadsGroupLocks:353jclass ThreadsGroupLocks;354jobject threadsGroupLocks;355jmethodID getBarrier;356357//CountDownLatch358jobject barrier;359jclass CountDownLatch;360361//Thread362jclass Thread;363364jlong sleepTime = 20 * 60 * 1000;365366367GET_OBJECT_CLASS(threadClass, obj);368369FIND_CLASS(loggerClass, SloggerClassName);370FIND_CLASS(ThreadsGroupLocks, "nsk/monitoring/share/ThreadsGroupLocks");371FIND_CLASS(CountDownLatch, "nsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch");372373GET_STATIC_OBJ_FIELD(STATE, threadClass, "STATE", "Ljava/lang/Thread$State;");374GET_OBJ_FIELD(threadsGroupLocks, obj, threadClass, "threadsGroupLocks", "Lnsk/monitoring/share/ThreadsGroupLocks;");375376// Thread.sleep(3600 * 1000);377FIND_CLASS(Thread, "java/lang/Thread");378379getBarrier = env->GetMethodID(ThreadsGroupLocks, "getBarrier",380"(Ljava/lang/Thread$State;)Lnsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch;");381barrier = env->CallObjectMethod(threadsGroupLocks, getBarrier, STATE);382CALL_VOID_NOPARAM(barrier, CountDownLatch, "countDown");383384CALL_STATIC_VOID(Thread, "sleep", "(J)V", sleepTime);385}386387/*388* Class: nsk_monitoring_share_RunningThread389* Method: nativeBringState390* Signature: ()V391*/392JNIEXPORT void JNICALL393Java_nsk_monitoring_share_RunningThread_nativeBringState(JNIEnv *env,394jobject obj) {395jobject logger;396jstring jmsg;397jfieldID field;398jmethodID method;399400jclass threadClass, loggerClass;401402//STATE403jobject STATE;404405//ThreadsGroupLocks:406jclass ThreadsGroupLocks;407jobject threadsGroupLocks;408jmethodID getBarrier;409410//CountDownLatch411jobject barrier;412jclass CountDownLatch;413414//Thread415jclass Thread;416417//runnableCanExit418jboolean flag = JNI_FALSE;419420GET_OBJECT_CLASS(threadClass, obj);421422FIND_CLASS(loggerClass, SloggerClassName);423FIND_CLASS(ThreadsGroupLocks, "nsk/monitoring/share/ThreadsGroupLocks");424FIND_CLASS(CountDownLatch, "nsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch");425426GET_STATIC_OBJ_FIELD(STATE, threadClass, "STATE", "Ljava/lang/Thread$State;");427GET_OBJ_FIELD(threadsGroupLocks, obj, threadClass, "threadsGroupLocks", "Lnsk/monitoring/share/ThreadsGroupLocks;");428429// Thread.sleep(3600 * 1000);430FIND_CLASS(Thread, "java/lang/Thread");431432getBarrier = env->GetMethodID(ThreadsGroupLocks, "getBarrier",433"(Ljava/lang/Thread$State;)Lnsk/monitoring/share/ThreadsGroupLocks$PlainCountDownLatch;");434435TRACE("running loop");436437barrier = env->CallObjectMethod(threadsGroupLocks, getBarrier, STATE);438CALL_VOID_NOPARAM(barrier, CountDownLatch, "countDown");439440// while (!threadsGroupLocks.runnableCanExit.get()) {441// Thread.yield();442// }443while (flag == JNI_FALSE)444{445GET_BOOL_FIELD(flag, threadsGroupLocks, ThreadsGroupLocks, "runnableCanExit");446CALL_STATIC_VOID_NOPARAM(Thread, "yield");447}448449}450451jstring getStateName(JNIEnv *env, jint state) {452switch (state & JVMTI_JAVA_LANG_THREAD_STATE_MASK) {453case JVMTI_JAVA_LANG_THREAD_STATE_NEW:454return env->NewStringUTF("NEW");455case JVMTI_JAVA_LANG_THREAD_STATE_TERMINATED:456return env->NewStringUTF("TERMINATED");457case JVMTI_JAVA_LANG_THREAD_STATE_RUNNABLE:458return env->NewStringUTF("RUNNABLE");459case JVMTI_JAVA_LANG_THREAD_STATE_BLOCKED:460return env->NewStringUTF("BLOCKED");461case JVMTI_JAVA_LANG_THREAD_STATE_WAITING:462return env->NewStringUTF("WAITING");463case JVMTI_JAVA_LANG_THREAD_STATE_TIMED_WAITING:464return env->NewStringUTF("TIMED_WAITING");465}466// should never reach467assert(0);468return 0;469}470471/*472* Class: nsk_monitoring_share_ThreadController473* Method: getThreadState474* Signature: (Ljava/lang/Thread;)Ljava/lang/Thread/State;475*/476JNIEXPORT jobject JNICALL477Java_nsk_monitoring_share_ThreadController_getThreadState(JNIEnv *env,478jobject obj, jobject thread) {479480JavaVM *vm;481jvmtiEnv *jvmti;482jclass ThreadState;483jmethodID method;484jobject threadState;485jstring stateName;486jint state;487488if (!NSK_VERIFY(env->GetJavaVM(&vm) == 0)) {489return NULL;490}491492if (!NSK_VERIFY(vm->GetEnv((void **)&jvmti, JVMTI_VERSION_1) == JNI_OK)) {493return NULL;494}495496if (!NSK_VERIFY(jvmti->GetThreadState((jthread)thread, &state) == JVMTI_ERROR_NONE)) {497return NULL;498}499500stateName = getStateName(env, state);501if (!NSK_JNI_VERIFY(env, (ThreadState = env->FindClass("java/lang/Thread$State")) != NULL))502return NULL;503504if (!NSK_JNI_VERIFY(env, (method = env->GetStaticMethodID(ThreadState, "valueOf", "(Ljava/lang/String;)Ljava/lang/Thread$State;")) != NULL))505return NULL;506threadState = env->CallStaticObjectMethod(ThreadState, method, stateName);507508return threadState;509}510511}512513514