< prev index next >

test/hotspot/jtreg/serviceability/jvmti/SuspendWithCurrentThread/libSuspendWithCurrentThread.cpp

Print this page
*** 22,36 ***
   */
  
  #include <string.h>
  #include <atomic>
  #include "jvmti.h"
  
  extern "C" {
  
  static jvmtiEnv* jvmti = NULL;
  static jthread* threads = NULL;
  static jsize threads_count = 0;
- static std::atomic<bool> is_exited_from_suspend;
- 
- #define LOG(...) \
-   do { \
-     printf(__VA_ARGS__); \
-     printf("\n"); \
-     fflush(stdout); \
-   } while (0)
- 
- static void
- check_jvmti_status(JNIEnv* jni, jvmtiError err, const char* msg) {
-   if (err != JVMTI_ERROR_NONE) {
-     LOG("check_jvmti_status: JVMTI function returned error: %d", err);
-     jni->FatalError(msg);
-   }
- }
  
  JNIEXPORT void JNICALL
  Java_SuspendWithCurrentThread_registerTestedThreads(JNIEnv *jni, jclass cls, jobjectArray threadsArr) {
!   LOG("\nregisterTestedThreads: started");
    threads_count = jni->GetArrayLength(threadsArr);
  
    jvmtiError err = jvmti->Allocate((threads_count * sizeof(jthread)),
                                     (unsigned char**)&threads);
    check_jvmti_status(jni, err, "registerTestedThreads: error in JVMTI Allocate threads array");
--- 22,21 ---
   */
  
  #include <string.h>
  #include <atomic>
  #include "jvmti.h"
+ #include "jvmti_common.h"
  
  extern "C" {
  
  static jvmtiEnv* jvmti = NULL;
  static jthread* threads = NULL;
  static jsize threads_count = 0;
  
  JNIEXPORT void JNICALL
  Java_SuspendWithCurrentThread_registerTestedThreads(JNIEnv *jni, jclass cls, jobjectArray threadsArr) {
!   LOG("\nregisterTestedThreads: started\n");
    threads_count = jni->GetArrayLength(threadsArr);
  
    jvmtiError err = jvmti->Allocate((threads_count * sizeof(jthread)),
                                     (unsigned char**)&threads);
    check_jvmti_status(jni, err, "registerTestedThreads: error in JVMTI Allocate threads array");

*** 66,72 ***
  /* This function is executed on the suspender thread which is not Main thread */
  JNIEXPORT void JNICALL
  Java_ThreadToSuspend_suspendTestedThreads(JNIEnv *jni, jclass cls) {
    jvmtiError* results = NULL;
    jvmtiError err;
  
!   LOG("\nsuspendTestedThreads: started");
    err = jvmti->Allocate((threads_count * sizeof(jvmtiError)),
                          (unsigned char**)&results);
    check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI Allocate results array");
  
!   LOG("suspendTestedThreads: before JVMTI SuspendThreadList");
    err = jvmti->SuspendThreadList(threads_count, threads, results);
!   is_exited_from_suspend.store(true);
    check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI SuspendThreadList");
  
!   LOG("suspendTestedThreads: check and print SuspendThreadList results:");
    for (int i = 0; i < threads_count; i++) {
!     LOG("  thread #%d: (%d)", i, (int)results[i]);
      check_jvmti_status(jni, results[i], "suspendTestedThreads: error in SuspendThreadList results[i]");
    }
!   LOG("suspendTestedThreads: finished\n");
  
    err = jvmti->Deallocate((unsigned char*)results);
    check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI Deallocate results");
  }
  
  JNIEXPORT jboolean JNICALL
  Java_SuspendWithCurrentThread_checkTestedThreadsSuspended(JNIEnv *jni, jclass cls) {
!   LOG("checkTestedThreadsSuspended: started");
  
    for (int i = 0; i < threads_count; i++) {
!     jint state = 0;
!     jvmtiError err = jvmti->GetThreadState(threads[i], &state);
!     check_jvmti_status(jni, err, "checkTestedThreadsSuspended: error in GetThreadState");
! 
!     if ((state & JVMTI_THREAD_STATE_SUSPENDED) == 0) {
!       LOG("thread #%d has not been suspended yet: "
!              "#   state: (%#x)", i, (int)state);
!       return JNI_FALSE;
      }
    }
!   if (is_exited_from_suspend.load()) {
!     LOG("Thread didn't stop in self suspend.");
!     return JNI_FALSE;
!   }
    LOG("checkTestedThreadsSuspended: finished\n");
    return JNI_TRUE;
  }
  
  JNIEXPORT void JNICALL
  Java_SuspendWithCurrentThread_resumeTestedThreads(JNIEnv *jni, jclass cls) {
    jvmtiError* results = NULL;
    jvmtiError err;
  
!   LOG("\nresumeTestedThreads: started");
    err = jvmti->Allocate((threads_count * sizeof(jvmtiError)),
                          (unsigned char**)&results);
    check_jvmti_status(jni, err, "resumeTestedThreads: error in JVMTI Allocate results array");
  
!   LOG("resumeTestedThreads: before JVMTI ResumeThreadList");
    err = jvmti->ResumeThreadList(threads_count, threads, results);
    check_jvmti_status(jni, err, "resumeTestedThreads: error in ResumeThreadList");
  
!   LOG("resumeTestedThreads: check and print ResumeThreadList results:");
    for (int i = 0; i < threads_count; i++) {
!     LOG("  thread #%d: (%d)", i, (int)results[i]);
      check_jvmti_status(jni, results[i], "resumeTestedThreads: error in ResumeThreadList results[i]");
    }
  
    err = jvmti->Deallocate((unsigned char*)results);
    check_jvmti_status(jni, err, "resumeTestedThreads: error in JVMTI Deallocate results");
--- 51,77 ---
  /* This function is executed on the suspender thread which is not Main thread */
  JNIEXPORT void JNICALL
  Java_ThreadToSuspend_suspendTestedThreads(JNIEnv *jni, jclass cls) {
    jvmtiError* results = NULL;
    jvmtiError err;
+   const char* tname = get_thread_name(jvmti, jni, NULL); // current thread name
  
!   LOG("\nsuspendTestedThreads: started by thread: %s\n", tname);
    err = jvmti->Allocate((threads_count * sizeof(jvmtiError)),
                          (unsigned char**)&results);
    check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI Allocate results array");
  
!   LOG("suspendTestedThreads: before JVMTI SuspendThreadList\n");
    err = jvmti->SuspendThreadList(threads_count, threads, results);
!   // is_exited_from_suspend.store(true); // TODO SERGUEI
    check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI SuspendThreadList");
  
!   LOG("suspendTestedThreads: check and print SuspendThreadList results:\n");
    for (int i = 0; i < threads_count; i++) {
!     LOG("  thread #%d suspend errcode: (%d)\n", i, (int)results[i]);
      check_jvmti_status(jni, results[i], "suspendTestedThreads: error in SuspendThreadList results[i]");
    }
!   LOG("suspendTestedThreads: finished by thread: %s\n", tname);
  
    err = jvmti->Deallocate((unsigned char*)results);
    check_jvmti_status(jni, err, "suspendTestedThreads: error in JVMTI Deallocate results");
+   err = jvmti->Deallocate((unsigned char*)tname);
  }
  
  JNIEXPORT jboolean JNICALL
  Java_SuspendWithCurrentThread_checkTestedThreadsSuspended(JNIEnv *jni, jclass cls) {
!   LOG("checkTestedThreadsSuspended: started\n");
  
    for (int i = 0; i < threads_count; i++) {
!     while (true) { // loop until a timeout happens if the thread is not suspended
!       jint state = 0;
!       jvmtiError err = jvmti->GetThreadState(threads[i], &state);
!       check_jvmti_status(jni, err, "checkTestedThreadsSuspended: error in GetThreadState");
! 
!       if ((state & JVMTI_THREAD_STATE_SUSPENDED) == 0) {
!         LOG("thread #%d has not been suspended yet: # state: (%#x)\n", i, (int)state);
!       } else {
+         break;
+       }
+       millisleep(10);
      }
    }
!   // if (is_exited_from_suspend.load()) { // TODO SERGUEI
!   //   LOG("Thread didn't stop in self suspend.");
!   //   return JNI_FALSE;
!   // }
    LOG("checkTestedThreadsSuspended: finished\n");
    return JNI_TRUE;
  }
  
  JNIEXPORT void JNICALL
  Java_SuspendWithCurrentThread_resumeTestedThreads(JNIEnv *jni, jclass cls) {
    jvmtiError* results = NULL;
    jvmtiError err;
  
!   LOG("\nresumeTestedThreads: started\n");
    err = jvmti->Allocate((threads_count * sizeof(jvmtiError)),
                          (unsigned char**)&results);
    check_jvmti_status(jni, err, "resumeTestedThreads: error in JVMTI Allocate results array");
  
!   LOG("resumeTestedThreads: before JVMTI ResumeThreadList\n");
    err = jvmti->ResumeThreadList(threads_count, threads, results);
    check_jvmti_status(jni, err, "resumeTestedThreads: error in ResumeThreadList");
  
!   LOG("resumeTestedThreads: check and print ResumeThreadList results:\n");
    for (int i = 0; i < threads_count; i++) {
!     LOG("  thread #%d resume errcode: (%d)\n", i, (int)results[i]);
      check_jvmti_status(jni, results[i], "resumeTestedThreads: error in ResumeThreadList results[i]");
    }
  
    err = jvmti->Deallocate((unsigned char*)results);
    check_jvmti_status(jni, err, "resumeTestedThreads: error in JVMTI Deallocate results");

*** 141,12 ***
  
  JNIEXPORT void JNICALL
  Java_SuspendWithCurrentThread_releaseTestedThreadsInfo(JNIEnv *jni, jclass cls) {
    jvmtiError err;
  
!   LOG("\nreleaseTestedThreadsInfo: started");
- 
    for (int i = 0; i < threads_count; i++) {
      if (threads[i] != NULL) {
        jni->DeleteGlobalRef(threads[i]);
      }
    }
--- 131,11 ---
  
  JNIEXPORT void JNICALL
  Java_SuspendWithCurrentThread_releaseTestedThreadsInfo(JNIEnv *jni, jclass cls) {
    jvmtiError err;
  
!   LOG("\nreleaseTestedThreadsInfo: started\n");
    for (int i = 0; i < threads_count; i++) {
      if (threads[i] != NULL) {
        jni->DeleteGlobalRef(threads[i]);
      }
    }

*** 159,12 ***
  
  /** Agent library initialization. */
  
  JNIEXPORT jint JNICALL
  Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
!   LOG("\nAgent_OnLoad started");
!   is_exited_from_suspend.store(false);
    // create JVMTI environment
    if (jvm->GetEnv((void **) (&jvmti), JVMTI_VERSION) != JNI_OK) {
      return JNI_ERR;
    }
  
--- 148,12 ---
  
  /** Agent library initialization. */
  
  JNIEXPORT jint JNICALL
  Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
!   LOG("\nAgent_OnLoad started\n");
! 
    // create JVMTI environment
    if (jvm->GetEnv((void **) (&jvmti), JVMTI_VERSION) != JNI_OK) {
      return JNI_ERR;
    }
  
< prev index next >