1 /*
2  * Copyright (c) 2003, 2019, 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 <stdlib.h>
25 #include <stdio.h>
26 #include <stdarg.h>
27 #include <string.h>
28 #include <ctype.h>
29 
30 /*************************************************************/
31 
32 #include "jvmti.h"
33 
34 /*************************************************************/
35 
36 #include "nsk_tools.h"
37 #include "jni_tools.h"
38 #include "jvmti_tools.h"
39 #include "JVMTITools.h"
40 
41 /*************************************************************/
42 
43 extern "C" {
44 
45 /*************************************************************/
46 
47 #define NSK_JVMTI_WAITTIME 2
48 
49 #define NSK_JVMTI_MAX_OPTIONS       10
50 #define NSK_JVMTI_OPTION_START      '-'
51 
52 #define NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE "pathToNewByteCode"
53 #define PATH_FORMAT "%s%02d/%s"
54 #define DIR_NAME "newclass"
55 
56 static volatile int redefineAttempted = NSK_FALSE;
57 static volatile int redefineSucceed = NSK_FALSE;
58 static volatile int agentFailed = NSK_FALSE;
59 
60 static struct {
61     struct {
62         int count;
63         char* names[NSK_JVMTI_MAX_OPTIONS];
64         char* values[NSK_JVMTI_MAX_OPTIONS];
65         char* string;
66     } options;
67     int waittime;
68 } context;
69 
70 /*************************************************************/
71 
check_option(int dashed,const char name[],const char value[])72 static int check_option(int dashed, const char name[], const char value[]) {
73     if (strcmp("verbose", name) == 0) {
74         if (strlen(value) > 0) {
75             nsk_complain("nsk_jvmti_parseOptions(): unexpected value in option: %s=%s\n", name, value);
76             return NSK_FALSE;
77         }
78         nsk_setVerboseMode(NSK_TRUE);
79     } else if (strcmp("trace", name) == 0) {
80         if (strlen(value) <= 0) {
81             nsk_complain("nsk_jvmti_parseOptions(): no value for option: %s\n", name);
82             return NSK_FALSE;
83         }
84         if (strcmp("none", value) == 0) {
85             nsk_setTraceMode(NSK_TRACE_NONE);
86         } else if (strcmp("before", value) == 0) {
87             nsk_setTraceMode(NSK_TRACE_BEFORE);
88         } else if (strcmp("after", value) == 0) {
89             nsk_setTraceMode(NSK_TRACE_AFTER);
90         } else if (strcmp("all", value) == 0) {
91             nsk_setTraceMode(NSK_TRACE_ALL);
92         } else {
93             nsk_complain("nsk_jvmti_parseOptions(): uexpected value in option: %s=%s\n", name, value);
94             return NSK_FALSE;
95         }
96         nsk_setVerboseMode(NSK_TRUE);
97     } else if (strcmp("waittime", name) == 0) {
98         if (strlen(value) <= 0) {
99             nsk_complain("nsk_jvmti_parseOptions(): no value for option: %s\n", name);
100             return NSK_FALSE;
101         }
102         {
103             char* end = NULL;
104             long n = strtol(value, &end, 10);
105             if (end == NULL || end == value || *end != '\0') {
106                 nsk_complain("nsk_jvmti_parseOptions(): not integer value in option: %s=%s\n", name, value);
107                 return NSK_FALSE;
108             }
109             if (n < 0) {
110                 nsk_complain("nsk_jvmti_parseOptions(): negative value in option: %s=%s\n", name, value);
111                 return NSK_FALSE;
112             }
113             context.waittime = (int)n;
114         }
115     } else if (dashed) {
116         nsk_complain("nsk_jvmti_parseOptions(): unknown option: %c%s\n",
117                                                         NSK_JVMTI_OPTION_START, name);
118         return NSK_FALSE;
119     }
120     return NSK_TRUE;
121 }
122 
add_option(const char opt[],int opt_len,const char val[],int val_len)123 static int add_option(const char opt[], int opt_len, const char val[], int val_len) {
124     char* name;
125     char* value;
126 
127     int success = NSK_TRUE;
128     int dashed_opt = NSK_FALSE;
129 
130     if (opt[0] == NSK_JVMTI_OPTION_START) {
131         dashed_opt = NSK_TRUE;
132         opt++;
133         opt_len--;
134     }
135     if (opt_len <= 0) {
136         nsk_complain("nsk_jvmti_parseOptions(): found empty option\n");
137         return NSK_FALSE;
138     }
139 
140     name = (char*)malloc(opt_len + 1);
141     value = (char*)malloc(val_len + 1);
142 
143     if (name == NULL || value == NULL) {
144         nsk_complain("nsk_jvmti_parseOptions(): out of memory\n");
145         success = NSK_FALSE;
146     } else {
147         strncpy(name, opt, opt_len);
148         name[opt_len] = '\0';
149         strncpy(value, val, val_len);
150         value[val_len] = '\0';
151 
152         if (!check_option(dashed_opt, name, value)) {
153             success = NSK_FALSE;
154         }
155     }
156 
157     if (success) {
158         if (context.options.count >= NSK_JVMTI_MAX_OPTIONS) {
159             nsk_complain("nsk_jvmti_parseOptions(): too many options for parsing\n");
160             success = NSK_FALSE;
161         } else {
162             context.options.names[context.options.count] = name;
163             context.options.values[context.options.count] = value;
164             context.options.count++;
165         }
166     }
167 
168     if (!success) {
169         if (name != NULL)
170             free(name);
171         if (value != NULL)
172             free(value);
173     }
174 
175     return success;
176 }
177 
nsk_jvmti_free()178 static void nsk_jvmti_free() {
179     if (context.options.count > 0) {
180         int i;
181         for (i = 0; i < context.options.count; i++) {
182             free(context.options.names[i]);
183             free(context.options.values[i]);
184         }
185         context.options.count = 0;
186     }
187     if (context.options.string != NULL) {
188         free(context.options.string);
189         context.options.string = NULL;
190     }
191 }
192 
193 
194 /*
195  * Tokenize a string based on a list of delimiters.
196  */
token(char ** s,const char * delim)197 static char* token(char **s, const char *delim) {
198   char *p;
199   char *start = *s;
200 
201   if (s == NULL || *s == NULL) {
202     return NULL;
203   }
204 
205   p = strpbrk(*s, delim);
206   if (p != NULL) {
207     /* Advance to next token. */
208     *p = '\0';
209     *s = p + 1;
210   } else {
211     /* End of tokens. */
212     *s = NULL;
213   }
214 
215   return start;
216 }
217 
nsk_jvmti_parseOptions(const char options[])218 int nsk_jvmti_parseOptions(const char options[]) {
219     int success = NSK_TRUE;
220 
221     char *str = NULL;
222     char *name = NULL;
223     char *value = NULL;
224     const char *delimiters = " ,~";
225     if (options == NULL)
226         return success;
227 
228     /*
229      * Save a copy of the full options string for
230      * ArgumentHandler.getAgentOptionsString().
231      */
232     context.options.string = strdup(options);
233 
234     /* Create a temporary copy of the options string to be tokenized. */
235     str = strdup(options);
236     while ((name = token(&str, delimiters)) != NULL) {
237         value = strchr(name, '=');
238 
239         if (value != NULL) {
240             *value++ = '\0';
241         }
242         if (!add_option(name, (int)strlen(name), value,
243                         value ? (int)strlen(value) : 0)) {
244             success = NSK_FALSE;
245             break;
246         }
247     }
248     if (!success) {
249         nsk_jvmti_free();
250     }
251     if (str != NULL) {
252       free(str);
253     }
254     return success;
255 }
256 
257 /*************************************************************/
258 
259 /**
260  * Returns value of given option name; or NULL if no such option found.
261  * If search name is NULL then complains an error and returns NULL.
262  */
nsk_jvmti_findOptionValue(const char name[])263 const char* nsk_jvmti_findOptionValue(const char name[]) {
264     int i;
265 
266     if (name == NULL) {
267         nsk_complain("nsk_jvmti_findOptionValue(): option name is NULL\n");
268         return NULL;
269     }
270 
271     for (i = 0; i < context.options.count; i++) {
272         if (strcmp(name, context.options.names[i]) == 0)
273             return context.options.values[i];
274     }
275     return NULL;
276 }
277 
278 /**
279  * Returns string value of given option; or defaultValue if no such option found.
280  * If options is specified but has empty value then complains an error and returns NULL.
281  */
nsk_jvmti_findOptionStringValue(const char name[],const char * defaultValue)282 const char* nsk_jvmti_findOptionStringValue(const char name[], const char* defaultValue) {
283     const char* value;
284 
285     if (name == NULL) {
286         nsk_complain("nsk_jvmti_findOptionStringValue(): option name is NULL\n");
287         return NULL;
288     }
289 
290     value = nsk_jvmti_findOptionValue(name);
291     if (value == NULL) {
292         return defaultValue;
293     }
294 
295     if (strlen(value) <= 0) {
296         nsk_complain("nsk_jvmti_findOptionStringValue(): empty value of option: %s=%s\n",
297                                                                             name, value);
298         return NULL;
299     }
300     return value;
301 }
302 
303 /**
304  * Returns integer value of given option; or defaultValue if no such option found.
305  * If options is specified but has no integer value then complains an error and returns -1.
306  */
nsk_jvmti_findOptionIntValue(const char name[],int defaultValue)307 int nsk_jvmti_findOptionIntValue(const char name[], int defaultValue) {
308     const char* value;
309 
310     if (name == NULL) {
311         nsk_complain("nsk_jvmti_findOptionIntValue(): option name is NULL\n");
312         return -1;
313     }
314 
315     value = nsk_jvmti_findOptionValue(name);
316     if (value == NULL) {
317         return defaultValue;
318     }
319 
320     if (strlen(value) <= 0) {
321         nsk_complain("nsk_jvmti_findOptionIntValue(): empty value of option: %s=%s\n",
322                                                                             name, value);
323         return -1;
324     }
325 
326     {
327         char* endptr = NULL;
328         int n = strtol(value, &endptr, 10);
329 
330         if (endptr == NULL || *endptr != '\0') {
331             nsk_complain("nsk_jvmti_findOptionIntValue(): not integer value of option: %s=%s\n",
332                                                                             name, value);
333             return -1;
334         }
335         return n;
336     }
337 }
338 
339 /**
340  * Returns number of parsed options.
341  */
nsk_jvmti_getOptionsCount()342 int nsk_jvmti_getOptionsCount() {
343     return context.options.count;
344 }
345 
346 /**
347  * Returns name of i-th parsed option.
348  * If no such option then complains an error and returns NULL.
349  */
nsk_jvmti_getOptionName(int i)350 const char* nsk_jvmti_getOptionName(int i) {
351     if (i < 0 || i >= context.options.count) {
352         nsk_complain("nsk_jvmti_getOptionName(): option index out of bounds: %d\n", i);
353         return NULL;
354     }
355     return context.options.names[i];
356 }
357 
358 /**
359  * Returns value of i-th parsed option.
360  * If no such option then complains an error and returns NULL.
361  */
nsk_jvmti_getOptionValue(int i)362 const char* nsk_jvmti_getOptionValue(int i) {
363     if (i < 0 || i >= context.options.count) {
364         nsk_complain("nsk_jvmti_getOptionValue(): option index out of bounds: %d\n", i);
365         return NULL;
366     }
367     return context.options.values[i];
368 }
369 
370 /*************************************************************/
371 
372 /**
373  * Returns value of -waittime option or default value if not specified.
374  */
nsk_jvmti_getWaitTime()375 int  nsk_jvmti_getWaitTime() {
376     return context.waittime;
377 }
378 
379 /**
380  * Sets specified waittime value.
381  */
nsk_jvmti_setWaitTime(int waittime)382 void nsk_jvmti_setWaitTime(int waittime) {
383     context.waittime = waittime;
384 }
385 
386 /*************************************************************/
387 
nsk_jvmti_lverify(int positive,jvmtiError error,jvmtiError expected,const char file[],int line,const char format[],...)388 int nsk_jvmti_lverify(int positive, jvmtiError error, jvmtiError expected,
389                         const char file[], int line, const char format[], ...)
390 {
391     int failure=0;
392     int negative = !positive;
393     int errorCode = (int)error;
394     const char* errorName = TranslateError(error);
395     va_list ap;
396     va_start(ap,format);
397     nsk_lvtrace(NSK_TRACE_AFTER,file,line,format,ap);
398     if (negative || expected != JVMTI_ERROR_NONE)
399         nsk_ltrace(NSK_TRACE_AFTER,file,line,
400             "  jvmti error: code=%d, name=%s\n",errorCode,errorName);
401     if ((error == expected) == negative) {
402         nsk_lvcomplain(file,line,format,ap);
403         nsk_printf("#   jvmti error: code=%d, name=%s\n",errorCode,errorName);
404         if (expected != JVMTI_ERROR_NONE)
405             nsk_printf("#   error expected: code=%d, name=%s\n",
406                 expected, TranslateError(expected));
407         failure=1;
408     };
409     va_end(ap);
410     return !failure;
411 }
412 
413 /*************************************************************/
414 
415 JNIEXPORT jstring JNICALL
Java_nsk_share_jvmti_ArgumentHandler_getAgentOptionsString(JNIEnv * jni,jobject obj)416 Java_nsk_share_jvmti_ArgumentHandler_getAgentOptionsString(JNIEnv *jni, jobject obj) {
417     jstring str_obj = NULL;
418 
419     if (!NSK_JNI_VERIFY(jni, (str_obj = jni->NewStringUTF(context.options.string)) != NULL)) {
420         return NULL;
421     }
422     return str_obj;
423 }
424 
425 /*************************************************************/
426 
427 /**
428   * This method will try to redefine the class (classToRedefine) by loading
429   * physical file.  <b>pathToNewByteCode</b> option which is passed
430   * on OnLoad Phase also used.
431   *
432   * So This method will do a file read pathToByteCode+fileName+.class (total path).
433   * Constrcuts a class objects and does a redefine of the class.
434   * On successfull redefine this method will return eaither JNI_TRUE or JNI_FALSE
435   *
436   * Hint::
437   *     1)
438   *      If there are many redefine on same testcase, then please try to use
439   *      integer value (newclass00, newclass01, newclass02 , ....) way.
440   *
441   *     2) When you compile these please do keep, a metatag on testcase as
442   *     # build : native classes classes.redef
443   *
444   *     3) When you do build these classes are psysically located in build as.
445   *
446   * TESTBASE/bin/newclass0* directory.
447   * eg: for nks/jvmti/scenarios/hotswap/HS204/hs204t001 you should see
448   * TESTBASE/bin/newclass0* /nsk/hotswap/HS204/hs204t001/MyClass.class
449   *
450   */
451 
nsk_jvmti_redefineClass(jvmtiEnv * jvmti,jclass classToRedefine,const char * fileName)452 int nsk_jvmti_redefineClass(jvmtiEnv * jvmti,
453         jclass classToRedefine,
454         const char * fileName) {
455     redefineAttempted = NSK_TRUE;
456     if (nsk_jvmti_findOptionValue(NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE) == NULL) {
457         nsk_printf("#   error expected: %s \n", NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE);
458         nsk_printf("Hint :: missing java -agentlib:agentlib=%s=DirName, ($TESTBASE/bin) \n",
459                    NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE);
460         return NSK_FALSE;
461     }
462     if (fileName == NULL) {
463         nsk_printf("# error file name expected did not found \n");
464         return NSK_FALSE;
465     }
466     {
467         char file [1024];
468         //= "DEFAULT";
469         sprintf(file,"%s/%s.class",
470                 nsk_jvmti_findOptionValue(NSK_JVMTI_OPT_PATH_TO_NEW_BYTE_CODE),
471                 fileName);
472         nsk_printf("# info :: File = %s \n",file);
473 
474         {
475             FILE *bytecode;
476             unsigned char * classBytes;
477             jvmtiError error;
478             jint size;
479 
480             bytecode = fopen(file, "rb");
481             error= JVMTI_ERROR_NONE;
482             if (bytecode == NULL) {
483                 nsk_printf("# error **Agent::error opening file %s \n",file);
484                 return NSK_FALSE;
485             }
486 
487             nsk_printf("#  info **Agent:: opening file %s \n",file);
488             fseek(bytecode, 0, SEEK_END);
489             size = ftell(bytecode);
490             nsk_printf("# info file size= %ld\n",ftell(bytecode));
491             rewind(bytecode);
492             error = jvmti->Allocate(size,&classBytes);
493             if (error != JVMTI_ERROR_NONE) {
494                 nsk_printf(" Failed to create memory %s \n",TranslateError(error));
495                 return NSK_FALSE;
496             }
497 
498             if (((jint) fread(classBytes, 1,size,bytecode)) != size) {
499                 nsk_printf(" # error failed to read all the bytes , could be less or more \n");
500                 return NSK_FALSE;
501             } else {
502                 nsk_printf(" File red completely \n");
503             }
504             fclose(bytecode);
505             {
506                 jvmtiClassDefinition classDef;
507                 classDef.klass = classToRedefine;
508                 classDef.class_byte_count= size;
509                 classDef.class_bytes = classBytes;
510                 error = jvmti->RedefineClasses(1,&classDef);
511                 if (error != JVMTI_ERROR_NONE) {
512                     nsk_printf("# error occured while redefining %s ",
513                             TranslateError(error));
514                     return NSK_FALSE;
515                 }
516             }
517         }
518     }
519     redefineSucceed= NSK_TRUE;
520     return NSK_TRUE;
521 }
522 
523 JNIEXPORT jboolean JNICALL
Java_nsk_share_jvmti_RedefineAgent_redefineAttempted(JNIEnv * jni,jobject obj)524 Java_nsk_share_jvmti_RedefineAgent_redefineAttempted(JNIEnv *jni,  jobject obj) {
525 
526     if (redefineAttempted) {
527         return JNI_TRUE;
528     }else {
529         return JNI_FALSE;
530     }
531 }
532 
533 
534 JNIEXPORT jboolean JNICALL
Java_nsk_share_jvmti_RedefineAgent_isRedefined(JNIEnv * jni,jobject obj)535 Java_nsk_share_jvmti_RedefineAgent_isRedefined(JNIEnv * jni,  jobject obj) {
536 
537     if (redefineSucceed) {
538         return JNI_TRUE;
539     }else {
540         return JNI_FALSE;
541     }
542 }
543 /**
544  * This jni method is a Java wrapper for agent status.
545  */
546 JNIEXPORT jboolean JNICALL
Java_nsk_share_jvmti_RedefineAgent_agentStatus(JNIEnv * jni,jobject obj)547 Java_nsk_share_jvmti_RedefineAgent_agentStatus(JNIEnv * jni,  jobject obj) {
548     if (agentFailed) {
549         return JNI_FALSE;
550     } else {
551         return JNI_TRUE;
552     }
553 }
554 
nsk_jvmti_getFileName(int redefineCnt,const char * dir,char * buf,size_t bufsize)555 void nsk_jvmti_getFileName(int redefineCnt, const char * dir,  char * buf, size_t bufsize) {
556    snprintf(buf, bufsize, PATH_FORMAT, DIR_NAME, redefineCnt, dir);
557    buf[bufsize-1] = '\0';
558 }
559 
nsk_jvmti_enableNotification(jvmtiEnv * jvmti,jvmtiEvent event,jthread thread)560 int nsk_jvmti_enableNotification(jvmtiEnv *jvmti,jvmtiEvent event, jthread thread) {
561     jvmtiError rc=JVMTI_ERROR_NONE;
562     rc = jvmti->SetEventNotificationMode(JVMTI_ENABLE, event, thread);
563     if (rc != JVMTI_ERROR_NONE) {
564         nsk_printf("# error Failed to set Notification for Event \n ");
565         return NSK_FALSE;
566     }
567     return NSK_TRUE;
568 }
569 
nsk_jvmti_disableNotification(jvmtiEnv * jvmti,jvmtiEvent event,jthread thread)570 int nsk_jvmti_disableNotification(jvmtiEnv *jvmti,jvmtiEvent event, jthread thread) {
571   jvmtiError rc=JVMTI_ERROR_NONE;
572   rc = jvmti->SetEventNotificationMode(JVMTI_DISABLE, event, thread);
573   if (rc != JVMTI_ERROR_NONE) {
574       nsk_printf(" Failed to disaable Notification for Event ");
575       return NSK_FALSE;
576   }
577   return NSK_TRUE;
578 }
579 
nsk_jvmti_agentFailed()580 void nsk_jvmti_agentFailed() {
581     agentFailed = NSK_TRUE;
582 }
583 
isThreadExpected(jvmtiEnv * jvmti,jthread thread)584 int isThreadExpected(jvmtiEnv *jvmti, jthread thread) {
585     static const char *vm_jfr_buffer_thread_name = "VM JFR Buffer Thread";
586     static const char *jfr_request_timer_thread_name = "JFR request timer";
587     static const char *graal_management_bean_registration_thread_name =
588                                             "HotSpotGraalManagement Bean Registration";
589     static const char *graal_compiler_thread_name_prefix = "JVMCI CompilerThread";
590     static const size_t prefixLength = strlen(graal_compiler_thread_name_prefix);
591 
592     jvmtiThreadInfo threadinfo;
593     NSK_JVMTI_VERIFY(jvmti->GetThreadInfo(thread, &threadinfo));
594 
595     if (strcmp(threadinfo.name, vm_jfr_buffer_thread_name) == 0)
596         return 0;
597 
598     if (strcmp(threadinfo.name, jfr_request_timer_thread_name) == 0)
599         return 0;
600 
601     if (strcmp(threadinfo.name, graal_management_bean_registration_thread_name) == 0)
602         return 0;
603 
604     if ((strlen(threadinfo.name) > prefixLength) &&
605          strncmp(threadinfo.name, graal_compiler_thread_name_prefix, prefixLength) == 0)
606         return 0;
607 
608     return 1;
609 }
610 
611 #define SLEEP_DELAY 10L
612 
suspendThreadAtMethod(jvmtiEnv * jvmti,jclass cls,jobject thread,jmethodID testMethod)613 int suspendThreadAtMethod(jvmtiEnv *jvmti, jclass cls, jobject thread, jmethodID testMethod) {
614     printf(">>>>>>>> Invoke SuspendThread()\n");
615 
616     jvmtiError err = jvmti->SuspendThread(thread);
617     if (err != JVMTI_ERROR_NONE) {
618         printf("%s: Failed to call SuspendThread(): error=%d: %s\n",
619                __FILE__, err, TranslateError(err));
620         return NSK_FALSE;
621     }
622 
623     int result = NSK_TRUE;
624     jmethodID method = NULL;
625     jlocation loc;
626 
627     // We need to ensure that the thread is suspended at the right place when the top
628     // frame belongs to the test rather than to incidental Java code (classloading,
629     // JVMCI, etc). Below we do resume/suspend in the loop until the target method
630     // is executed in the top frame or the loop counter exceeds the limit.
631     for (int i = 0; i < 10; i++) {
632         err = jvmti->GetFrameLocation(thread, 0, &method, &loc);
633         if (err != JVMTI_ERROR_NONE) {
634             printf("(GetFrameLocation) unexpected error: %s (%d)\n",
635                    TranslateError(err), err);
636             result = NSK_FALSE;
637             break;
638         }
639 
640         char *name, *sig, *generic;
641         jvmti->GetMethodName(method, &name, &sig, &generic);
642         printf(">>> Attempt %d to suspend the thread. Top frame: \"%s%s\"\n",
643                i, name, sig);
644         if (method == testMethod) break;
645 
646         err = jvmti->ResumeThread(thread);
647         if (err != JVMTI_ERROR_NONE) {
648             printf("(ResumeThread) unexpected error: %s (%d)\n",
649                    TranslateError(err), err);
650             result = NSK_FALSE;
651         }
652 
653         mssleep(SLEEP_DELAY);
654 
655         err = jvmti->SuspendThread(thread);
656         if (err != JVMTI_ERROR_NONE) {
657             printf("(SuspendThread) unexpected error: %s (%d)\n",
658                    TranslateError(err), err);
659             result = NSK_FALSE;
660         }
661     }
662     if(method == testMethod) {
663         printf("<<<<<<<< SuspendThread() is successfully done\n");
664     } else {
665         char *name, *sig, *generic;
666         jvmti->GetMethodName(testMethod, &name, &sig, &generic);
667         printf("Failed in the suspendThread: was not able to suspend thread "
668                "with required method \"%s%s\" on the top\n", name, sig);
669         result = NSK_FALSE;
670     }
671     return result;
672 }
673 
createRawMonitor(jvmtiEnv * env,const char * name,jrawMonitorID * monitor)674 jint createRawMonitor(jvmtiEnv *env, const char *name, jrawMonitorID *monitor) {
675     jvmtiError error = env->CreateRawMonitor(name, monitor);
676     if (!NSK_JVMTI_VERIFY(error)) {
677         return JNI_ERR;
678     }
679     return JNI_OK;
680 }
681 
exitOnError(jvmtiError error)682 void exitOnError(jvmtiError error) {
683     if (!NSK_JVMTI_VERIFY(error)) {
684         exit(error);
685     }
686 }
687 
rawMonitorEnter(jvmtiEnv * env,jrawMonitorID monitor)688 void rawMonitorEnter(jvmtiEnv *env, jrawMonitorID monitor) {
689     jvmtiError error = env->RawMonitorEnter(monitor);
690     exitOnError(error);
691 }
692 
rawMonitorExit(jvmtiEnv * env,jrawMonitorID monitor)693 void rawMonitorExit(jvmtiEnv *env, jrawMonitorID monitor) {
694     jvmtiError error = env->RawMonitorExit(monitor);
695     exitOnError(error);
696 }
697 
rawMonitorNotify(jvmtiEnv * env,jrawMonitorID monitor)698 void rawMonitorNotify(jvmtiEnv *env, jrawMonitorID monitor) {
699     jvmtiError error = env->RawMonitorNotify(monitor);
700     exitOnError(error);
701 }
702 
rawMonitorWait(jvmtiEnv * env,jrawMonitorID monitor,jlong millis)703 void rawMonitorWait(jvmtiEnv *env, jrawMonitorID monitor, jlong millis) {
704     jvmtiError error = env->RawMonitorWait(monitor, millis);
705     exitOnError(error);
706 }
707 
getPhase(jvmtiEnv * env,jvmtiPhase * phase)708 void getPhase(jvmtiEnv *env, jvmtiPhase *phase) {
709     jvmtiError error = env->GetPhase(phase);
710     exitOnError(error);
711 }
712 
713 /*************************************************************/
714 
715 }
716