test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadState/thrstat002/thrstat002.cpp
changeset 51551 e409244ce72e
parent 50260 46c67f5e27c2
child 51672 b613bf6a10b1
equal deleted inserted replaced
51550:a2f1923b3e16 51551:e409244ce72e
       
     1 /*
       
     2  * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.
       
     8  *
       
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    12  * version 2 for more details (a copy is included in the LICENSE file that
       
    13  * accompanied this code).
       
    14  *
       
    15  * You should have received a copy of the GNU General Public License version
       
    16  * 2 along with this work; if not, write to the Free Software Foundation,
       
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    18  *
       
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    20  * or visit www.oracle.com if you need additional information or have any
       
    21  * questions.
       
    22  */
       
    23 
       
    24 #include <stdio.h>
       
    25 #include <string.h>
       
    26 #include "jvmti.h"
       
    27 #include "agent_common.h"
       
    28 #include "JVMTITools.h"
       
    29 
       
    30 #ifdef __cplusplus
       
    31 extern "C" {
       
    32 #endif
       
    33 
       
    34 #ifndef JNI_ENV_ARG
       
    35 
       
    36 #ifdef __cplusplus
       
    37 #define JNI_ENV_ARG(x, y) y
       
    38 #define JNI_ENV_PTR(x) x
       
    39 #else
       
    40 #define JNI_ENV_ARG(x,y) x, y
       
    41 #define JNI_ENV_PTR(x) (*x)
       
    42 #endif
       
    43 
       
    44 #endif
       
    45 
       
    46 #define PASSED  0
       
    47 #define STATUS_FAILED  2
       
    48 #define WAIT_START 100
       
    49 
       
    50 static jvmtiEnv *jvmti = NULL;
       
    51 static jvmtiCapabilities caps;
       
    52 static jvmtiEventCallbacks callbacks;
       
    53 static jrawMonitorID access_lock, wait_lock;
       
    54 static jint result = PASSED;
       
    55 static jboolean printdump = JNI_FALSE;
       
    56 static jthread thr_ptr = NULL;
       
    57 static jint wait_time = 0;
       
    58 static jint state[] = {
       
    59     JVMTI_THREAD_STATE_RUNNABLE,
       
    60     JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
       
    61     JVMTI_THREAD_STATE_IN_OBJECT_WAIT
       
    62 };
       
    63 
       
    64 void printStateFlags(jint flags) {
       
    65     if (flags & JVMTI_THREAD_STATE_SUSPENDED)
       
    66         printf(" JVMTI_THREAD_STATE_SUSPENDED");
       
    67     if (flags & JVMTI_THREAD_STATE_INTERRUPTED)
       
    68         printf(" JVMTI_THREAD_STATE_INTERRUPTED");
       
    69     if (flags & JVMTI_THREAD_STATE_IN_NATIVE)
       
    70         printf(" JVMTI_THREAD_STATE_IN_NATIVE");
       
    71     printf(" (0x%0x)\n", flags);
       
    72 }
       
    73 
       
    74 void JNICALL VMInit(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thr) {
       
    75     jvmtiError err;
       
    76 
       
    77     err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE,
       
    78         JVMTI_EVENT_THREAD_START, NULL);
       
    79     if (err != JVMTI_ERROR_NONE) {
       
    80         printf("Failed to enable THREAD_START event: %s (%d)\n",
       
    81                TranslateError(err), err);
       
    82         result = STATUS_FAILED;
       
    83     }
       
    84 }
       
    85 
       
    86 void JNICALL
       
    87 ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) {
       
    88     jvmtiThreadInfo thrInfo;
       
    89     jvmtiError err;
       
    90 
       
    91     err = jvmti_env->RawMonitorEnter(access_lock);
       
    92     if (err != JVMTI_ERROR_NONE) {
       
    93         printf("(RawMonitorEnter) unexpected error: %s (%d)\n",
       
    94                TranslateError(err), err);
       
    95         result = STATUS_FAILED;
       
    96     }
       
    97 
       
    98     err = jvmti_env->GetThreadInfo(thread, &thrInfo);
       
    99     if (err != JVMTI_ERROR_NONE) {
       
   100         printf("(GetThreadInfo) unexpected error: %s (%d)\n",
       
   101                TranslateError(err), err);
       
   102         result = STATUS_FAILED;
       
   103     }
       
   104     if (thrInfo.name != NULL && strcmp(thrInfo.name, "thr1") == 0) {
       
   105         thr_ptr = JNI_ENV_PTR(env)->NewGlobalRef(JNI_ENV_ARG((JNIEnv *)env, thread));
       
   106         if (printdump == JNI_TRUE) {
       
   107             printf(">>> ThreadStart: \"%s\", 0x%p\n", thrInfo.name, thr_ptr);
       
   108         }
       
   109     }
       
   110 
       
   111     err = jvmti_env->RawMonitorExit(access_lock);
       
   112     if (err != JVMTI_ERROR_NONE) {
       
   113         printf("(RawMonitorExit) unexpected error: %s (%d)\n",
       
   114                TranslateError(err), err);
       
   115         result = STATUS_FAILED;
       
   116     }
       
   117 }
       
   118 
       
   119 #ifdef STATIC_BUILD
       
   120 JNIEXPORT jint JNICALL Agent_OnLoad_thrstat002(JavaVM *jvm, char *options, void *reserved) {
       
   121     return Agent_Initialize(jvm, options, reserved);
       
   122 }
       
   123 JNIEXPORT jint JNICALL Agent_OnAttach_thrstat002(JavaVM *jvm, char *options, void *reserved) {
       
   124     return Agent_Initialize(jvm, options, reserved);
       
   125 }
       
   126 JNIEXPORT jint JNI_OnLoad_thrstat002(JavaVM *jvm, char *options, void *reserved) {
       
   127     return JNI_VERSION_1_8;
       
   128 }
       
   129 #endif
       
   130 jint  Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
       
   131     jint res;
       
   132     jvmtiError err;
       
   133 
       
   134     if (options != NULL && strcmp(options, "printdump") == 0) {
       
   135         printdump = JNI_TRUE;
       
   136     }
       
   137 
       
   138     res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
       
   139         JVMTI_VERSION_1_1);
       
   140     if (res != JNI_OK || jvmti == NULL) {
       
   141         printf("Wrong result of a valid call to GetEnv !\n");
       
   142         return JNI_ERR;
       
   143     }
       
   144 
       
   145     err = jvmti->GetPotentialCapabilities(&caps);
       
   146     if (err != JVMTI_ERROR_NONE) {
       
   147         printf("(GetPotentialCapabilities) unexpected error: %s (%d)\n",
       
   148                TranslateError(err), err);
       
   149         return JNI_ERR;
       
   150     }
       
   151 
       
   152     err = jvmti->AddCapabilities(&caps);
       
   153     if (err != JVMTI_ERROR_NONE) {
       
   154         printf("(AddCapabilities) unexpected error: %s (%d)\n",
       
   155                TranslateError(err), err);
       
   156         return JNI_ERR;
       
   157     }
       
   158 
       
   159     err = jvmti->GetCapabilities(&caps);
       
   160     if (err != JVMTI_ERROR_NONE) {
       
   161         printf("(GetCapabilities) unexpected error: %s (%d)\n",
       
   162                TranslateError(err), err);
       
   163         return JNI_ERR;
       
   164     }
       
   165 
       
   166     if (!caps.can_suspend) {
       
   167         printf("Warning: suspend/resume is not implemented\n");
       
   168     }
       
   169 
       
   170     err = jvmti->CreateRawMonitor("_access_lock", &access_lock);
       
   171     if (err != JVMTI_ERROR_NONE) {
       
   172         printf("(CreateRawMonitor) unexpected error: %s (%d)\n",
       
   173                TranslateError(err), err);
       
   174         return JNI_ERR;
       
   175     }
       
   176 
       
   177     err = jvmti->CreateRawMonitor("_wait_lock", &wait_lock);
       
   178     if (err != JVMTI_ERROR_NONE) {
       
   179         printf("(CreateRawMonitor) unexpected error: %s (%d)\n",
       
   180                TranslateError(err), err);
       
   181         return JNI_ERR;
       
   182     }
       
   183 
       
   184     callbacks.VMInit = &VMInit;
       
   185     callbacks.ThreadStart = &ThreadStart;
       
   186     err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
       
   187     if (err != JVMTI_ERROR_NONE) {
       
   188         printf("(SetEventCallbacks) unexpected error: %s (%d)\n",
       
   189                TranslateError(err), err);
       
   190         return JNI_ERR;
       
   191     }
       
   192 
       
   193     err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
       
   194         JVMTI_EVENT_VM_INIT, NULL);
       
   195     if (err != JVMTI_ERROR_NONE) {
       
   196         printf("Failed to enable VM_INIT event: %s (%d)\n",
       
   197                TranslateError(err), err);
       
   198         result = STATUS_FAILED;
       
   199     }
       
   200 
       
   201     return JNI_OK;
       
   202 }
       
   203 
       
   204 JNIEXPORT void JNICALL
       
   205 Java_nsk_jvmti_GetThreadState_thrstat002_init(JNIEnv *env, jclass cls,
       
   206         jint waitTime) {
       
   207     wait_time = waitTime * 60000;
       
   208 }
       
   209 
       
   210 void wait_for(jint millis) {
       
   211     jvmtiError err;
       
   212 
       
   213     err = jvmti->RawMonitorEnter(wait_lock);
       
   214     if (err != JVMTI_ERROR_NONE) {
       
   215         printf("(RawMonitorEnter#check) unexpected error: %s (%d)\n",
       
   216                TranslateError(err), err);
       
   217         result = STATUS_FAILED;
       
   218     }
       
   219     err = jvmti->RawMonitorWait(wait_lock, (jlong)millis);
       
   220     if (err != JVMTI_ERROR_NONE) {
       
   221         printf("(RawMonitorWait#check) unexpected error: %s (%d)\n",
       
   222                TranslateError(err), err);
       
   223         result = STATUS_FAILED;
       
   224     }
       
   225     err = jvmti->RawMonitorExit(wait_lock);
       
   226     if (err != JVMTI_ERROR_NONE) {
       
   227         printf("(RawMonitorExit#check) unexpected error: %s (%d)\n",
       
   228                TranslateError(err), err);
       
   229         result = STATUS_FAILED;
       
   230     }
       
   231 }
       
   232 
       
   233 JNIEXPORT void JNICALL
       
   234 Java_nsk_jvmti_GetThreadState_thrstat002_checkStatus(JNIEnv *env, jclass cls,
       
   235         jint statInd, jboolean suspended) {
       
   236     jint thrState;
       
   237     jint suspState = -1;
       
   238     jint right_stat = (suspended ? JVMTI_THREAD_STATE_SUSPENDED : 0);
       
   239     jvmtiError right_ans = (suspended ? JVMTI_ERROR_THREAD_SUSPENDED : JVMTI_ERROR_NONE);
       
   240     const char *suspStr = (suspended ? ", suspended" : "");
       
   241     jvmtiError err;
       
   242     jint millis;
       
   243     jboolean timeout_is_reached;
       
   244     unsigned int waited_millis;
       
   245 
       
   246     if (jvmti == NULL) {
       
   247         printf("JVMTI client was not properly loaded!\n");
       
   248         result = STATUS_FAILED;
       
   249         return;
       
   250     }
       
   251 
       
   252     if (thr_ptr == NULL) {
       
   253         printf("Missing thread \"thr1\" start event\n");
       
   254         result = STATUS_FAILED;
       
   255         return;
       
   256     }
       
   257 
       
   258     if (!caps.can_suspend) {
       
   259         return;
       
   260     }
       
   261 
       
   262     printf( "START checkStatus for \"thr1\" (0x%p%s), check state: %s\n",
       
   263             thr_ptr, suspStr, TranslateState(state[statInd]) );
       
   264 
       
   265     timeout_is_reached = JNI_TRUE;
       
   266     for (millis = WAIT_START, waited_millis=0; millis < wait_time; millis <<= 1) {
       
   267         err = jvmti->GetThreadState(thr_ptr, &thrState);
       
   268         if (err != JVMTI_ERROR_NONE) {
       
   269             printf("(GetThreadState#%d) unexpected error: %s (%d)\n",
       
   270                 statInd, TranslateError(err), err);
       
   271             result = STATUS_FAILED;
       
   272             timeout_is_reached = JNI_FALSE;
       
   273             break;
       
   274         }
       
   275         suspState = thrState & JVMTI_THREAD_STATE_SUSPENDED;
       
   276         if (suspended || (thrState & JVMTI_THREAD_STATE_RUNNABLE) == 0 ||
       
   277             (state[statInd] == JVMTI_THREAD_STATE_RUNNABLE)) {
       
   278             timeout_is_reached = JNI_FALSE;
       
   279             break;
       
   280         }
       
   281 
       
   282         waited_millis += millis;
       
   283         wait_for(millis);
       
   284     }
       
   285 
       
   286     if (printdump == JNI_TRUE) {
       
   287         printf(">>> thread \"thr1\" (0x%p) state: %s (%d)\n",
       
   288             thr_ptr, TranslateState(thrState), thrState);
       
   289         printf(">>>\tflags:");
       
   290         printStateFlags(suspState);
       
   291     }
       
   292 
       
   293     if (timeout_is_reached == JNI_TRUE) {
       
   294         printf("Error: timeout (%d secs) has been reached\n", waited_millis/1000);
       
   295     }
       
   296     if ((thrState & state[statInd]) == 0) {
       
   297         printf("Wrong thread \"thr1\" (0x%p%s) state:\n", thr_ptr, suspStr);
       
   298         printf("    expected: %s (%d)\n",
       
   299             TranslateState(state[statInd]), state[statInd]);
       
   300         printf("      actual: %s (%d)\n",
       
   301             TranslateState(thrState), thrState);
       
   302         result = STATUS_FAILED;
       
   303     }
       
   304     if (suspState != right_stat) {
       
   305         printf("Wrong thread \"thr1\" (0x%p%s) state flags:\n",
       
   306                thr_ptr, suspStr);
       
   307         printf("    expected:");
       
   308         printStateFlags(right_stat);
       
   309         printf("    actual:");
       
   310         printStateFlags(suspState);
       
   311         result = STATUS_FAILED;
       
   312     }
       
   313 
       
   314     err = jvmti->SuspendThread(thr_ptr);
       
   315     if (err != right_ans) {
       
   316         printf("Wrong result of SuspendThread() for \"thr1\" (0x%p%s):\n",
       
   317                thr_ptr, suspStr);
       
   318         printf("    expected: %s (%d), actual: %s (%d)\n",
       
   319             TranslateError(right_ans), right_ans, TranslateError(err), err);
       
   320         result = STATUS_FAILED;
       
   321     }
       
   322 
       
   323     if (!suspended) {
       
   324         // wait till thread is not suspended
       
   325         timeout_is_reached = JNI_TRUE;
       
   326         for (millis = WAIT_START, waited_millis=0; millis < wait_time; millis <<= 1) {
       
   327             waited_millis += millis;
       
   328             wait_for(millis);
       
   329             err = jvmti->GetThreadState(thr_ptr, &thrState);
       
   330             if (err != JVMTI_ERROR_NONE) {
       
   331                 printf("(GetThreadState#%d,after) unexpected error: %s (%d)\n",
       
   332                     statInd, TranslateError(err), err);
       
   333                 timeout_is_reached = JNI_FALSE;
       
   334                 result = STATUS_FAILED;
       
   335                 break;
       
   336             }
       
   337             suspState = thrState & JVMTI_THREAD_STATE_SUSPENDED;
       
   338             if (suspState) {
       
   339                 timeout_is_reached = JNI_FALSE;
       
   340                 break;
       
   341             }
       
   342         }
       
   343 
       
   344         if (timeout_is_reached == JNI_TRUE) {
       
   345             printf("Error: timeout (%d secs) has been reached\n", waited_millis/1000);
       
   346         }
       
   347         if ((thrState & state[statInd]) == 0) {
       
   348             printf("Wrong thread \"thr1\" (0x%p) state after SuspendThread:\n",
       
   349                 thr_ptr);
       
   350             printf("    expected: %s (%d)\n",
       
   351                 TranslateState(state[statInd]), state[statInd]);
       
   352             printf("      actual: %s (%d)\n",
       
   353                 TranslateState(thrState), thrState);
       
   354             result = STATUS_FAILED;
       
   355         }
       
   356         if (suspState != JVMTI_THREAD_STATE_SUSPENDED) {
       
   357             printf("Wrong thread \"thr1\" (0x%p) state flags", thr_ptr);
       
   358             printf(" after SuspendThread:\n");
       
   359             printf("    expected:");
       
   360             printStateFlags(JVMTI_THREAD_STATE_SUSPENDED);
       
   361             printf("    actual:");
       
   362             printStateFlags(suspState);
       
   363             result = STATUS_FAILED;
       
   364         }
       
   365         err = jvmti->ResumeThread(thr_ptr);
       
   366         if (err != JVMTI_ERROR_NONE) {
       
   367             printf("(ResumeThread#%d) unexpected error: %s (%d)\n",
       
   368                 statInd, TranslateError(err), err);
       
   369             result = STATUS_FAILED;
       
   370         }
       
   371     }
       
   372 }
       
   373 
       
   374 JNIEXPORT jint JNICALL
       
   375 Java_nsk_jvmti_GetThreadState_thrstat002_getRes(JNIEnv *env, jclass cls) {
       
   376     return result;
       
   377 }
       
   378 
       
   379 #ifdef __cplusplus
       
   380 }
       
   381 #endif