test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/sampling/SP03/sp03t001/sp03t001.c
changeset 50260 46c67f5e27c2
equal deleted inserted replaced
50259:01d27ae7a84e 50260:46c67f5e27c2
       
     1 /*
       
     2  * Copyright (c) 2003, 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 <string.h>
       
    25 #include "jvmti.h"
       
    26 #include "agent_common.h"
       
    27 #include "jni_tools.h"
       
    28 #include "jvmti_tools.h"
       
    29 
       
    30 #ifdef __cplusplus
       
    31 extern "C" {
       
    32 #endif
       
    33 
       
    34 /* ============================================================================= */
       
    35 
       
    36 /* scaffold objects */
       
    37 static JNIEnv* jni = NULL;
       
    38 static jvmtiEnv *jvmti = NULL;
       
    39 static jlong timeout = 0;
       
    40 
       
    41 /* number of tested threads */
       
    42 #define THREADS_KINDS           6
       
    43 #define DEFAULT_THREADS_NUMBER  1
       
    44 
       
    45 /* names of tested threads */
       
    46 static const char* threadsName[THREADS_KINDS] = {
       
    47     "ThreadRunning",
       
    48     "ThreadEntering",
       
    49     "ThreadWaiting",
       
    50     "ThreadSleeping",
       
    51     "ThreadRunningInterrupted",
       
    52     "ThreadRunningNative"
       
    53 };
       
    54 
       
    55 /* expected states of tested threads */
       
    56 #define JVMTI_THREAD_STATE_NOT_STARTED 0
       
    57 static jint threadsState[THREADS_KINDS] = {
       
    58     JVMTI_THREAD_STATE_RUNNABLE,
       
    59     JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER,
       
    60     JVMTI_THREAD_STATE_IN_OBJECT_WAIT,
       
    61     JVMTI_THREAD_STATE_SLEEPING,
       
    62     JVMTI_THREAD_STATE_RUNNABLE,
       
    63     JVMTI_THREAD_STATE_RUNNABLE
       
    64 };
       
    65 
       
    66 /* references to tested threads */
       
    67 static jthread* threadsList[THREADS_KINDS];
       
    68 static int threadsCounts[THREADS_KINDS];
       
    69 static int threadsCount = 0;
       
    70 
       
    71 /* indexes of known threads */
       
    72 static const int interruptedThreadIndex = THREADS_KINDS - 2;
       
    73 static const int nativeThreadIndex = THREADS_KINDS - 1;
       
    74 
       
    75 /* ============================================================================= */
       
    76 
       
    77 /* testcase(s) */
       
    78 static int prepare();
       
    79 static int checkThreads(int suspended, const char* kind, jlong timeout);
       
    80 static int suspendThreadsList(int suspend);
       
    81 static int suspendThreadsIndividually(int suspend);
       
    82 static int clean();
       
    83 
       
    84 /* ============================================================================= */
       
    85 
       
    86 /** Agent algorithm. */
       
    87 static void JNICALL
       
    88 agentProc(jvmtiEnv* jvmti, JNIEnv* agentJNI, void* arg) {
       
    89     jni = agentJNI;
       
    90 
       
    91     /* wait for initial sync */
       
    92     if (!nsk_jvmti_waitForSync(timeout))
       
    93         return;
       
    94 
       
    95     /* perform testcase(s) */
       
    96     {
       
    97         /* prepare data: find threads */
       
    98         if (!prepare()) {
       
    99             nsk_jvmti_setFailStatus();
       
   100             return;
       
   101         }
       
   102 
       
   103         /* testcase #1: check not suspended threads */
       
   104         NSK_DISPLAY0("Testcase #1: check state of not suspended threads\n");
       
   105         if (!checkThreads(NSK_FALSE, "not suspended", timeout))
       
   106             return;
       
   107 
       
   108         /* suspend threads */
       
   109         NSK_DISPLAY0("Suspend threads list\n");
       
   110         if (!suspendThreadsList(NSK_TRUE))
       
   111             return;
       
   112 
       
   113         /* testcase #2: check suspended threads */
       
   114         NSK_DISPLAY0("Testcase #2: check state of suspended threads\n");
       
   115         if (!checkThreads(NSK_TRUE, "suspended", 0))
       
   116             return;
       
   117 
       
   118         /* resume threads */
       
   119         NSK_DISPLAY0("Resume threads list\n");
       
   120         if (!suspendThreadsList(NSK_FALSE))
       
   121             return;
       
   122 
       
   123         /* testcase #3: check resumed threads */
       
   124         NSK_DISPLAY0("Testcase #3: check state of resumed threads\n");
       
   125         if (!checkThreads(NSK_FALSE, "resumed", 0))
       
   126             return;
       
   127 
       
   128         /* clean date: delete threads references */
       
   129         if (!clean()) {
       
   130             nsk_jvmti_setFailStatus();
       
   131             return;
       
   132         }
       
   133     }
       
   134 
       
   135     /* resume debugee after last sync */
       
   136     if (!nsk_jvmti_resumeSync())
       
   137         return;
       
   138 }
       
   139 
       
   140 /* ============================================================================= */
       
   141 
       
   142 /**
       
   143  * Prepare data:
       
   144  *    - clean threads list
       
   145  *    - get all live threads
       
   146  *    - get threads name
       
   147  *    - find tested threads
       
   148  *    - make global refs
       
   149  */
       
   150 static int prepare() {
       
   151     jthread *allThreadsList = NULL;
       
   152     jint allThreadsCount = 0;
       
   153     int notfound = 0;
       
   154     int i, j;
       
   155 
       
   156     NSK_DISPLAY1("Prepare: find tested threads: %d kinds\n", THREADS_KINDS);
       
   157 
       
   158     /* allocate and clean threads list */
       
   159     for (i = 0; i < THREADS_KINDS; i++) {
       
   160         threadsCounts[i] = 0;
       
   161         threadsList[i] = NULL;
       
   162 
       
   163         if (!NSK_JVMTI_VERIFY(
       
   164                 NSK_CPP_STUB3(Allocate, jvmti, (threadsCount * sizeof(jthread)),
       
   165                                                     (unsigned char**)&threadsList[i])))
       
   166             return NSK_FALSE;
       
   167 
       
   168         for (j = 0; j < threadsCount; j++) {
       
   169             threadsList[i][j] = NULL;
       
   170         }
       
   171     }
       
   172 
       
   173     /* get all live threads */
       
   174     if (!NSK_JVMTI_VERIFY(
       
   175             NSK_CPP_STUB3(GetAllThreads, jvmti, &allThreadsCount, &allThreadsList)))
       
   176         return NSK_FALSE;
       
   177 
       
   178     if (!NSK_VERIFY(allThreadsCount > 0 && allThreadsList != NULL))
       
   179         return NSK_FALSE;
       
   180 
       
   181     /* find tested threads */
       
   182     for (i = 0; i < allThreadsCount; i++) {
       
   183         jvmtiThreadInfo threadInfo;
       
   184 
       
   185         if (!NSK_VERIFY(allThreadsList[i] != NULL))
       
   186             return NSK_FALSE;
       
   187 
       
   188         /* get thread name (info) */
       
   189         if (!NSK_JVMTI_VERIFY(
       
   190                 NSK_CPP_STUB3(GetThreadInfo, jvmti, allThreadsList[i], &threadInfo)))
       
   191             return NSK_FALSE;
       
   192 
       
   193         /* find by name */
       
   194         if (threadInfo.name != NULL) {
       
   195             for (j = 0; j < THREADS_KINDS; j++) {
       
   196                 if (strcmp(threadInfo.name, threadsName[j]) == 0) {
       
   197                     int k = threadsCounts[j];
       
   198                     if (k < threadsCount)
       
   199                         threadsList[j][k] = allThreadsList[i];
       
   200                     threadsCounts[j]++;
       
   201                 }
       
   202             }
       
   203         }
       
   204     }
       
   205 
       
   206     /* deallocate all threads list */
       
   207     if (!NSK_JVMTI_VERIFY(
       
   208             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)allThreadsList)))
       
   209         return NSK_FALSE;
       
   210 
       
   211     /* check if all tested threads found */
       
   212     notfound = 0;
       
   213     for (i = 0; i < THREADS_KINDS; i++) {
       
   214         if (threadsCounts[i] != threadsCount) {
       
   215             NSK_COMPLAIN3("Found unexpected number of tested threads (%s):\n"
       
   216                             "#   found:    %d\n"
       
   217                             "#   expected: %d\n",
       
   218                             threadsName[i], threadsCounts[i], threadsCount);
       
   219             nsk_jvmti_setFailStatus();
       
   220             notfound++;
       
   221         }
       
   222     }
       
   223 
       
   224     if (notfound > 0)
       
   225         return NSK_FALSE;
       
   226 
       
   227     /* make global refs */
       
   228     for (i = 0; i < THREADS_KINDS; i++) {
       
   229         for (j = 0; j < threadsCount; j++) {
       
   230             if (!NSK_JNI_VERIFY(jni, (threadsList[i][j] =
       
   231                     NSK_CPP_STUB2(NewGlobalRef, jni, threadsList[i][j])) != NULL))
       
   232                 return NSK_FALSE;
       
   233         }
       
   234     }
       
   235 
       
   236     return NSK_TRUE;
       
   237 }
       
   238 
       
   239 /**
       
   240  * Suspend or resume tested threads list.
       
   241  */
       
   242 static int suspendThreadsList(int suspend) {
       
   243     jlong resultsSize = threadsCount * sizeof(jvmtiError);
       
   244     jvmtiError* results = NULL;
       
   245     const char* kind = (suspend ? "suspending" : "resuming");
       
   246     int i, j;
       
   247 
       
   248     /* allocate results array */
       
   249     if (!NSK_JVMTI_VERIFY(
       
   250             NSK_CPP_STUB3(Allocate, jvmti, resultsSize, (unsigned char**)&results))) {
       
   251         nsk_jvmti_setFailStatus();
       
   252         return NSK_FALSE;
       
   253     }
       
   254 
       
   255     for (i = 0; i < THREADS_KINDS; i++) {
       
   256         /* suspend or resume threads list */
       
   257         if (suspend) {
       
   258             if (!NSK_JVMTI_VERIFY(
       
   259                     NSK_CPP_STUB4(SuspendThreadList, jvmti, threadsCount,
       
   260                                                         threadsList[i], results)))
       
   261                 nsk_jvmti_setFailStatus();
       
   262         } else {
       
   263             if (!NSK_JVMTI_VERIFY(
       
   264                     NSK_CPP_STUB4(ResumeThreadList, jvmti, threadsCount,
       
   265                                                         threadsList[i], results)))
       
   266                 nsk_jvmti_setFailStatus();
       
   267         }
       
   268 
       
   269         /* check results */
       
   270         for (j = 0; j < threadsCount; j++) {
       
   271             if (results[j] != JVMTI_ERROR_NONE) {
       
   272                 NSK_COMPLAIN5("Unexpected result of %s thread #%d (%s):\n"
       
   273                                 "#   got result: %s (%d)\n",
       
   274                                 kind, j, threadsName[i],
       
   275                                 TranslateError(results[j]), (int)results[j]);
       
   276                 nsk_jvmti_setFailStatus();
       
   277             }
       
   278         }
       
   279     }
       
   280 
       
   281     /* deallocate results array */
       
   282     if (!NSK_JVMTI_VERIFY(
       
   283             NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)results))) {
       
   284         nsk_jvmti_setFailStatus();
       
   285     }
       
   286 
       
   287     return NSK_TRUE;
       
   288 }
       
   289 
       
   290 /**
       
   291  * Suspend or resume tested threads individually.
       
   292  */
       
   293 static int suspendThreadsIndividually(int suspend) {
       
   294     int i, j;
       
   295 
       
   296     for (i = 0; i < THREADS_KINDS; i++) {
       
   297         for (j = 0; j < threadsCount; j++) {
       
   298             if (suspend) {
       
   299                 NSK_DISPLAY2("    suspend thread #%d (%s)\n", j, threadsName[i]);
       
   300                 if (!NSK_JVMTI_VERIFY(
       
   301                         NSK_CPP_STUB2(SuspendThread, jvmti, threadsList[i][j])))
       
   302                     nsk_jvmti_setFailStatus();
       
   303             } else {
       
   304                 NSK_DISPLAY2("    resume thread #%d (%s)\n", j, threadsName[i]);
       
   305                 if (!NSK_JVMTI_VERIFY(
       
   306                         NSK_CPP_STUB2(ResumeThread, jvmti, threadsList[i][j])))
       
   307                     nsk_jvmti_setFailStatus();
       
   308             }
       
   309         }
       
   310     }
       
   311     return NSK_TRUE;
       
   312 }
       
   313 
       
   314 /**
       
   315  * Testcase: check tested threads
       
   316  *    - get thread state and state flag
       
   317  *    - wait for WAITIME if state is not expected
       
   318  *    - check if thread state is as expected
       
   319  *
       
   320  * Returns NSK_TRUE if test may continue; or NSK_FALSE for test break.
       
   321  */
       
   322 static int checkThreads(int suspended, const char* kind, jlong timeout) {
       
   323     int i, j;
       
   324 
       
   325     /* check each thread */
       
   326     for (i = 0; i < THREADS_KINDS; i++) {
       
   327         for (j = 0; j < threadsCount; j++) {
       
   328             jint state = JVMTI_THREAD_STATE_NOT_STARTED;
       
   329             jlong t = 0;
       
   330 
       
   331             NSK_DISPLAY2("    thread #%d (%s):\n", j, threadsName[i]);
       
   332 
       
   333             /* get thread state */
       
   334             if (!NSK_JVMTI_VERIFY(
       
   335                     NSK_CPP_STUB3(GetThreadState, jvmti, threadsList[i][j], &state))) {
       
   336                 nsk_jvmti_setFailStatus();
       
   337                 return NSK_FALSE;
       
   338             }
       
   339 
       
   340             NSK_DISPLAY2("        state  = %s (%d)\n",
       
   341                                         TranslateState(state), (int)state);
       
   342 
       
   343             /* check SUSPENDED state */
       
   344             if (suspended) {
       
   345                 if (!(state & JVMTI_THREAD_STATE_SUSPENDED)) {
       
   346                     NSK_COMPLAIN5("No SUSPENDED state for %s thread #%d (%s):\n"
       
   347                                     "#    got flags: %s (%d)\n",
       
   348                                     kind, j, threadsName[i],
       
   349                                     TranslateState(state), (int)state);
       
   350                     nsk_jvmti_setFailStatus();
       
   351                 }
       
   352             } else {
       
   353                 if (state & JVMTI_THREAD_STATE_SUSPENDED) {
       
   354                     NSK_COMPLAIN5("Unexpected SUSPENDED state for %s thread #%d (%s):\n"
       
   355                                     "#   got flags: %s (%d)\n",
       
   356                                     kind, j, threadsName[i],
       
   357                                     TranslateState(state), (int)state);
       
   358                     nsk_jvmti_setFailStatus();
       
   359                 }
       
   360             }
       
   361         }
       
   362     }
       
   363 
       
   364     /* test may continue */
       
   365     return NSK_TRUE;
       
   366 }
       
   367 
       
   368 /**
       
   369  * Clean data:
       
   370  *   - dispose global references to tested threads
       
   371  */
       
   372 static int clean() {
       
   373     int i, j;
       
   374 
       
   375     /* dispose global references to threads */
       
   376     for (i = 0; i < THREADS_KINDS; i++) {
       
   377         for (j = 0; j < threadsCount; j++) {
       
   378             NSK_TRACE(NSK_CPP_STUB2(DeleteGlobalRef, jni, threadsList[i][j]));
       
   379         }
       
   380     }
       
   381 
       
   382     /* deallocate memory */
       
   383     for (i = 0; i < THREADS_KINDS; i++) {
       
   384         if (!NSK_JVMTI_VERIFY(
       
   385                 NSK_CPP_STUB2(Deallocate, jvmti, (unsigned char*)threadsList[i])))
       
   386             return NSK_FALSE;
       
   387         threadsList[i] = NULL;
       
   388     }
       
   389 
       
   390     return NSK_TRUE;
       
   391 }
       
   392 
       
   393 /* ============================================================================= */
       
   394 
       
   395 static volatile int testedThreadRunning = NSK_FALSE;
       
   396 static volatile int testedThreadShouldFinish = NSK_FALSE;
       
   397 
       
   398 /** Native running method in tested thread. */
       
   399 JNIEXPORT void JNICALL
       
   400 Java_nsk_jvmti_scenarios_sampling_SP03_sp03t001ThreadRunningNative_nativeMethod(JNIEnv* jni,
       
   401                                                                                      jobject obj) {
       
   402     volatile int i = 0, n = 1000;
       
   403 
       
   404     /* run in a loop */
       
   405     testedThreadRunning = NSK_TRUE;
       
   406     while (!testedThreadShouldFinish) {
       
   407         if (n <= 0)
       
   408             n = 1000;
       
   409         if (i >= n)
       
   410             i = 0;
       
   411         i++;
       
   412     }
       
   413     testedThreadRunning = NSK_FALSE;
       
   414 }
       
   415 
       
   416 /** Wait for native method is running. */
       
   417 JNIEXPORT jboolean JNICALL
       
   418 Java_nsk_jvmti_scenarios_sampling_SP03_sp03t001ThreadRunningNative_checkReady(JNIEnv* jni,
       
   419                                                                                    jobject obj) {
       
   420     while (!testedThreadRunning) {
       
   421         nsk_jvmti_sleep(1000);
       
   422     }
       
   423     return testedThreadRunning ? JNI_TRUE : JNI_FALSE;
       
   424 }
       
   425 
       
   426 /* Let native method to finish. */
       
   427 JNIEXPORT void JNICALL
       
   428 Java_nsk_jvmti_scenarios_sampling_SP03_sp03t001ThreadRunningNative_letFinish(JNIEnv* jni,
       
   429                                                                                   jobject obj) {
       
   430     testedThreadShouldFinish = NSK_TRUE;
       
   431 }
       
   432 
       
   433 /* ============================================================================= */
       
   434 
       
   435 /** Agent library initialization. */
       
   436 #ifdef STATIC_BUILD
       
   437 JNIEXPORT jint JNICALL Agent_OnLoad_sp03t001(JavaVM *jvm, char *options, void *reserved) {
       
   438     return Agent_Initialize(jvm, options, reserved);
       
   439 }
       
   440 JNIEXPORT jint JNICALL Agent_OnAttach_sp03t001(JavaVM *jvm, char *options, void *reserved) {
       
   441     return Agent_Initialize(jvm, options, reserved);
       
   442 }
       
   443 JNIEXPORT jint JNI_OnLoad_sp03t001(JavaVM *jvm, char *options, void *reserved) {
       
   444     return JNI_VERSION_1_8;
       
   445 }
       
   446 #endif
       
   447 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
       
   448 
       
   449     /* init framework and parse options */
       
   450     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
       
   451         return JNI_ERR;
       
   452 
       
   453     timeout = nsk_jvmti_getWaitTime() * 60 * 1000;
       
   454 
       
   455     /* get number of threads for each kind */
       
   456     threadsCount = nsk_jvmti_findOptionIntValue("threads", DEFAULT_THREADS_NUMBER);
       
   457     if (!NSK_VERIFY(threadsCount > 0))
       
   458         return JNI_ERR;
       
   459 
       
   460     /* create JVMTI environment */
       
   461     if (!NSK_VERIFY((jvmti =
       
   462             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
       
   463         return JNI_ERR;
       
   464 
       
   465     /* add specific capabilities for suspending thread */
       
   466     {
       
   467         jvmtiCapabilities suspendCaps;
       
   468         memset(&suspendCaps, 0, sizeof(suspendCaps));
       
   469         suspendCaps.can_suspend = 1;
       
   470         if (!NSK_JVMTI_VERIFY(
       
   471                 NSK_CPP_STUB2(AddCapabilities, jvmti, &suspendCaps)))
       
   472             return JNI_ERR;
       
   473     }
       
   474 
       
   475     /* register agent proc and arg */
       
   476     if (!NSK_VERIFY(nsk_jvmti_setAgentProc(agentProc, NULL)))
       
   477         return JNI_ERR;
       
   478 
       
   479     return JNI_OK;
       
   480 }
       
   481 
       
   482 /* ============================================================================= */
       
   483 
       
   484 #ifdef __cplusplus
       
   485 }
       
   486 #endif