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