From 174d62652c69e811cf44ab64db575b13a848a728 Mon Sep 17 00:00:00 2001
From: Serguei Spitsyn <sspitsyn@openjdk.org>
Date: Wed, 24 Apr 2024 09:02:02 +0000
Subject: [PATCH] 8328741:
 serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java failed with
 unexpected owner

Reviewed-by: lmesnik, cjplummer
---
 .../ObjectMonitorUsage.java                   | 18 ++--
 .../libObjectMonitorUsage.cpp                 | 84 ++-----------------
 .../SuspendResumeAll/libSuspendResumeAll.cpp  |  6 +-
 test/lib/jdk/test/lib/jvmti/jvmti_common.hpp  | 20 ++++-
 4 files changed, 34 insertions(+), 94 deletions(-)

diff --git a/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java b/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java
index 891306a0c11..bc9a0c5cabc 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java
+++ b/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/ObjectMonitorUsage.java
@@ -53,9 +53,9 @@ public class ObjectMonitorUsage {
     static Object lockCheck = new Object();
 
     native static int getRes();
-    native static int waitsToEnter();
-    native static int waitsToBeNotified();
     native static int setTestedMonitor(Object monitor);
+    native static void ensureBlockedOnEnter(Thread thread);
+    native static void ensureWaitingToBeNotified(Thread thread);
     native static void check(Object obj, Thread owner,
                              int entryCount, int waiterCount, int notifyWaiterCount);
 
@@ -87,10 +87,9 @@ public class ObjectMonitorUsage {
         Thread[] threads = new Thread[NUMBER_OF_WAITING_THREADS];
         for (int i = 0; i < NUMBER_OF_WAITING_THREADS; i++) {
             // the WaitingTask has to wait to be notified in lockCheck.wait()
-            threads[i] = startTask(i, new WaitingTask(), isVirtual, "Waiting");
-        }
-        while (waitsToBeNotified() < NUMBER_OF_WAITING_THREADS) {
-            sleep(1);
+            Thread thread = startTask(i, new WaitingTask(), isVirtual, "Waiting");
+            ensureWaitingToBeNotified(thread);
+            threads[i] = thread;
         }
         return threads;
     }
@@ -99,10 +98,9 @@ public class ObjectMonitorUsage {
         Thread[] threads = new Thread[NUMBER_OF_ENTERING_THREADS];
         for (int i = 0; i < NUMBER_OF_ENTERING_THREADS; i++) {
             // the EnteringTask has to be blocked at the lockCheck enter
-            threads[i] = startTask(i, new EnteringTask(), isVirtual, "Entering");
-        }
-        while (waitsToEnter() < NUMBER_OF_ENTERING_THREADS) {
-            sleep(1);
+            Thread thread = startTask(i, new EnteringTask(), isVirtual, "Entering");
+            ensureBlockedOnEnter(thread);
+            threads[i] = thread;
         }
         return threads;
     }
diff --git a/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/libObjectMonitorUsage.cpp b/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/libObjectMonitorUsage.cpp
index 015f64452e8..8575ae454a9 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/libObjectMonitorUsage.cpp
+++ b/test/hotspot/jtreg/serviceability/jvmti/ObjectMonitorUsage/libObjectMonitorUsage.cpp
@@ -32,11 +32,8 @@ extern "C" {
 #define STATUS_FAILED 2
 
 static jvmtiEnv *jvmti = nullptr;
-static jrawMonitorID event_lock = nullptr;
 static jint result = PASSED;
 static int check_idx = 0;
-static int waits_to_enter = 0;
-static int waits_to_be_notified = 0;
 static jobject tested_monitor = nullptr;
 
 static bool is_tested_monitor(JNIEnv *jni, jobject monitor) {
@@ -53,47 +50,10 @@ static void log_event(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread,
   deallocate(jvmti, jni, (void*)tname);
 }
 
-JNIEXPORT void JNICALL
-MonitorContendedEnter(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jobject monitor) {
-  RawMonitorLocker rml(jvmti, jni, event_lock);
-  if (is_tested_monitor(jni, monitor)) {
-    waits_to_enter++;
-    log_event(jvmti, jni, thread, "MonitorContendedEnter", waits_to_enter);
-  }
-}
-
-JNIEXPORT void JNICALL
-MonitorContendedEntered(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jobject monitor) {
-  RawMonitorLocker rml(jvmti, jni, event_lock);
-  if (is_tested_monitor(jni, monitor)) {
-    waits_to_enter--;
-    log_event(jvmti, jni, thread, "MonitorContendedEntered", waits_to_enter);
-  }
-}
-
-JNIEXPORT void JNICALL
-MonitorWait(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jobject monitor, jlong timeout) {
-  RawMonitorLocker rml(jvmti, jni, event_lock);
-  if (is_tested_monitor(jni, monitor)) {
-    waits_to_be_notified++;
-    log_event(jvmti, jni, thread, "MonitorWait", waits_to_be_notified);
-  }
-}
-
-JNIEXPORT void JNICALL
-MonitorWaited(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jobject monitor, jboolean timed_out) {
-  RawMonitorLocker rml(jvmti, jni, event_lock);
-  if (is_tested_monitor(jni, monitor)) {
-    waits_to_be_notified--;
-    log_event(jvmti, jni, thread, "MonitorWaited", waits_to_be_notified);
-  }
-}
-
 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
   jint res;
   jvmtiError err;
   jvmtiCapabilities caps;
-  jvmtiEventCallbacks callbacks;
 
   res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
   if (res != JNI_OK || jvmti == nullptr) {
@@ -116,17 +76,6 @@ jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
     LOG("Warning: Monitor events are not implemented\n");
     return JNI_ERR;
   }
-  memset(&callbacks, 0, sizeof(callbacks));
-  callbacks.MonitorContendedEnter   = &MonitorContendedEnter;
-  callbacks.MonitorContendedEntered = &MonitorContendedEntered;
-  callbacks.MonitorWait = &MonitorWait;
-  callbacks.MonitorWaited = &MonitorWaited;
-
-  err = jvmti->SetEventCallbacks(&callbacks, sizeof(jvmtiEventCallbacks));
-  check_jvmti_error(err, "Agent_Initialize: error in JVMTI SetEventCallbacks");
-
-  event_lock = create_raw_monitor(jvmti, "Events Monitor");
-
   return JNI_OK;
 }
 
@@ -216,41 +165,20 @@ Java_ObjectMonitorUsage_check(JNIEnv *jni, jclass cls, jobject obj, jthread owne
 
 JNIEXPORT void JNICALL
 Java_ObjectMonitorUsage_setTestedMonitor(JNIEnv *jni, jclass cls, jobject monitor) {
-  jvmtiError err;
-  jvmtiEventMode event_mode = (monitor != nullptr) ? JVMTI_ENABLE : JVMTI_DISABLE;
-
-  RawMonitorLocker rml(jvmti, jni, event_lock);
-
   if (tested_monitor != nullptr) {
     jni->DeleteGlobalRef(tested_monitor);
   }
   tested_monitor = (monitor != nullptr) ? jni->NewGlobalRef(monitor) : nullptr;
-  waits_to_enter = 0;
-  waits_to_be_notified = 0;
-
-  err = jvmti->SetEventNotificationMode(event_mode, JVMTI_EVENT_MONITOR_CONTENDED_ENTER, nullptr);
-  check_jvmti_status(jni, err, "setTestedMonitor: error in JVMTI SetEventNotificationMode #1");
-
-  err = jvmti->SetEventNotificationMode(event_mode, JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, nullptr);
-  check_jvmti_status(jni, err, "setTestedMonitor: error in JVMTI SetEventNotificationMode #2");
-
-  err = jvmti->SetEventNotificationMode(event_mode, JVMTI_EVENT_MONITOR_WAIT, nullptr);
-  check_jvmti_status(jni, err, "setTestedMonitor: error in JVMTI SetEventNotificationMode #3");
-
-  err = jvmti->SetEventNotificationMode(event_mode, JVMTI_EVENT_MONITOR_WAITED, nullptr);
-  check_jvmti_status(jni, err, "setTestedMonitor: error in JVMTI SetEventNotificationMode #4");
 }
 
-JNIEXPORT jint JNICALL
-Java_ObjectMonitorUsage_waitsToEnter(JNIEnv *jni, jclass cls) {
-  RawMonitorLocker rml(jvmti, jni, event_lock);
-  return waits_to_enter;
+JNIEXPORT void JNICALL
+Java_ObjectMonitorUsage_ensureBlockedOnEnter(JNIEnv *jni, jclass cls, jthread thread) {
+  wait_for_state(jvmti, jni, thread, JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER);
 }
 
-JNIEXPORT jint JNICALL
-Java_ObjectMonitorUsage_waitsToBeNotified(JNIEnv *jni, jclass cls) {
-  RawMonitorLocker rml(jvmti, jni, event_lock);
-  return waits_to_be_notified;
+JNIEXPORT void JNICALL
+Java_ObjectMonitorUsage_ensureWaitingToBeNotified(JNIEnv *jni, jclass cls, jthread thread) {
+  wait_for_state(jvmti, jni, thread, JVMTI_THREAD_STATE_WAITING_INDEFINITELY);
 }
 
 JNIEXPORT jint JNICALL
diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendResumeAll/libSuspendResumeAll.cpp b/test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendResumeAll/libSuspendResumeAll.cpp
index e53484b575b..bea9a9c19a9 100644
--- a/test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendResumeAll/libSuspendResumeAll.cpp
+++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/SuspendResumeAll/libSuspendResumeAll.cpp
@@ -216,11 +216,7 @@ test_vthread_resume_all(JNIEnv* jni, const jthread* thread_list, int suspend_mas
   check_jvmti_status(jni, err, "test_vthread_resume_all: error in JVMTI ResumeAllVirtualThreads");
 
   // wait a second to give the breakpoints a chance to be hit.
-#ifdef WINDOWS
-  Sleep(1000);
-#else
-  sleep(1);
-#endif
+  sleep_sec(1);
 
   for (int idx = 0; idx < EXCLUDE_CNT; idx++) {
     // Disable Breakpoint events on excluded thread
diff --git a/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp b/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp
index 9fdd4cf4cb8..693baf98d1f 100644
--- a/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp
+++ b/test/lib/jdk/test/lib/jvmti/jvmti_common.hpp
@@ -56,7 +56,7 @@
 
 #define COMPLAIN LOG
 
-
+void sleep_ms(int millis);
 const char* TranslateState(jint flags);
 const char* TranslateError(jvmtiError err);
 
@@ -380,6 +380,24 @@ find_method(jvmtiEnv *jvmti, JNIEnv *jni, jclass klass, const char* mname) {
   return method;
 }
 
+// Wait for target thread to reach the required JVMTI thread state.
+// The state jint bitmask is returned by the JVMTI GetThreadState.
+// Some examples are:
+// - JVMTI_THREAD_STATE_WAITING
+// - JVMTI_THREAD_STATE_BLOCKED_ON_MONITOR_ENTER
+// - JVMTI_THREAD_STATE_SLEEPING
+static void
+wait_for_state(jvmtiEnv *jvmti, JNIEnv *jni, jthread thread, jint exp_state) {
+  while (true) {
+    // Allow a bitmask to designate expected thread state. E.g., if two bits are expected
+    // than check they both are present in the state mask returned by JVMTI GetThreadState.
+    if ((get_thread_state(jvmti, jni, thread) & exp_state) == exp_state) {
+      break;
+    }
+    sleep_ms(100);
+  }
+}
+
 #define MAX_FRAME_COUNT_PRINT_STACK_TRACE 200
 
 static void