Skip to content
Permalink
Browse files
WaitNotifySuspendedVThreadTest test added.
  • Loading branch information
lmesnik committed Mar 11, 2021
1 parent 5fb7d58 commit 84f2f5ebe4c9f31ab0cee58a11afbf2d5d1972b3
Show file tree
Hide file tree
Showing 2 changed files with 250 additions and 0 deletions.
@@ -0,0 +1,82 @@
/*
* Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

/*
* @test
*
* @summary Test verifies set/get TLS data and verifies it's consistency.
* Test set TLS with thread name which it belongs to and verify this information when getting test.
* -- cbThreadStart
* -- by AgentThread
*
* Test doesn't verify that TLS is not NULL because for some threads TLS is not initialized initially.
* TODO:
* -- verify that TLS is not NULL (not possible to do with jvmti, ThreadStart might be called too late)
* -- add more events where TLS is set *first time*, it is needed to test lazily jvmtThreadState init
* -- set/get TLS from other JavaThreads (not from agent and current thread)
* -- set/get for suspened (blocked?) threads
* -- split test to "sanity" and "stress" version
* -- update properties to run jvmti stress tests non-concurrently?
*
*
* @library /test/lib
* @run main/othervm/native -Djava.util.concurrent.ForkJoinPool.common.parallelism=1 -agentlib:WaitNotifySuspendedVThread WaitNotifySuspendedVThreadTest
*/


import java.util.ArrayList;

public class WaitNotifySuspendedVThreadTest {

static {
System.loadLibrary("WaitNotifySuspendedVThread");
}

public static Object holder = new Object();


public static void main(String argv[]) throws InterruptedException {

WaitNotifySuspendedVThreadTask.setBreakpoint();
WaitNotifySuspendedVThreadTask task = new WaitNotifySuspendedVThreadTask();
Thread t = Thread.ofVirtual().start(task);

Thread.sleep(1000);
WaitNotifySuspendedVThreadTask.notifyRawMonitors(t);
t.join();
}
}


class WaitNotifySuspendedVThreadTask implements Runnable {
static native void setBreakpoint();
static native void notifyRawMonitors(Thread t);

void methBreakpoint() {
WaitNotifySuspendedVThreadTest.holder = new Object();
}

public void run() {
methBreakpoint();
}
}
@@ -0,0 +1,168 @@
/*
* Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/

#include <string.h>
#include "jvmti.h"
#include "jvmti_common.h"

jrawMonitorID monitor;
jrawMonitorID monitor_completed;

jvmtiEnv *jvmti_env;


static void
set_breakpoint(JNIEnv *jni, jclass klass, const char *mname)
{
jlocation location = (jlocation)0L;
jmethodID method = find_method(jvmti_env, jni, klass, mname);
jvmtiError err;

if (method == NULL) {
jni->FatalError("Error in set_breakpoint: not found method");
}
err = jvmti_env->SetBreakpoint(method, location);
check_jvmti_status(jni, err, "set_or_clear_breakpoint: error in JVMTI SetBreakpoint");

fflush(0);
}

extern "C" {
JNIEXPORT void JNICALL
Java_WaitNotifySuspendedVThreadTask_setBreakpoint(JNIEnv *jni, jclass klass) {
jvmtiError err;

printf("setBreakpoint: started\n");
set_breakpoint(jni, klass, "methBreakpoint");

// Enable Breakpoint events globally
err = jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_BREAKPOINT, NULL);
check_jvmti_status(jni, err, "enableEvents: error in JVMTI SetEventNotificationMode: enable BREAKPOINT");

printf("setBreakpoint: finished\n");
fflush(0);
}

JNIEXPORT void JNICALL
Java_WaitNotifySuspendedVThreadTask_notifyRawMonitors(JNIEnv *jni, jclass klass, jthread thread) {
jthread cthread;
check_jvmti_status(jni, jvmti_env->SuspendThread(thread), "SuspendThread thread");
check_jvmti_status(jni, jvmti_env->GetCarrierThread(thread, &cthread), "GetCarrierThread thread");
check_jvmti_status(jni, jvmti_env->SuspendThread(cthread), "SuspendThread thread");
{
RawMonitorLocker rml(jvmti_env, jni, monitor);
printf("Calling notifyAll()\n");
rml.notify_all();
}
RawMonitorLocker completed(jvmti_env, jni, monitor_completed);
check_jvmti_status(jni, jvmti_env->ResumeThread(thread), "ResumeThread thread");

// Test hang if cthread is not resumed
check_jvmti_status(jni, jvmti_env->ResumeThread(cthread), "ResumeThread cthread");

completed.wait();

}
}

static void JNICALL
Breakpoint(jvmtiEnv *jvmti, JNIEnv* jni, jthread thread,
jmethodID method, jlocation location) {
char* mname = get_method_name(jvmti, jni, method);

if (strcmp(mname, "methBreakpoint") != 0) {
printf("FAILED: got unexpected breakpoint in method %s()\n", mname);
deallocate(jvmti, jni, (void*)mname);
fatal(jni, "Error in breakpoint");
return;
}
char* tname = get_thread_name(jvmti, jni, thread);
const char* virt = jni->IsVirtualThread(thread) ? "virtual" : "carrier";

{
RawMonitorLocker rml(jvmti, jni, monitor);
printf("Breakpoint in wait(): %s in %s thread: %s\n", mname, virt, tname);
fflush(0);
rml.wait();
printf("Breakpoint after wait(): %s in %s thread: %s\n", mname, virt, tname);
}

RawMonitorLocker completed(jvmti, jni, monitor_completed);
completed.notify_all();

deallocate(jvmti, jni, (void*)tname);
deallocate(jvmti, jni, (void*)mname);
}

/* ============================================================================= */

jint Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
jvmtiEnv * jvmti = NULL;

jvmtiEventCallbacks callbacks;
jvmtiCapabilities caps;
jvmtiError err;
jint res;

res = jvm->GetEnv((void **) &jvmti, JVMTI_VERSION_1_1);
if (res != JNI_OK || jvmti == NULL) {
printf("Wrong result of a valid call to GetEnv!\n");
return JNI_ERR;
}

jvmti_env = jvmti;
monitor = create_raw_monitor(jvmti, "Monitor");
monitor_completed = create_raw_monitor(jvmti, "Monitor Completed");

/* add capability to generate compiled method events */
memset(&caps, 0, sizeof(jvmtiCapabilities));
caps.can_support_virtual_threads = 1;
caps.can_generate_breakpoint_events = 1;
caps.can_suspend = 1;

err = jvmti->AddCapabilities(&caps);
if (err != JVMTI_ERROR_NONE) {
printf("(AddCapabilities) unexpected error: %s (%d)\n",
TranslateError(err), err);
return JNI_ERR;
}

err = jvmti->GetCapabilities(&caps);
if (err != JVMTI_ERROR_NONE) {
printf("(GetCapabilities) unexpected error: %s (%d)\n",
TranslateError(err), err);
return JNI_ERR;
}

/* set event callback */
printf("setting event callbacks ...\n");
(void) memset(&callbacks, 0, sizeof(callbacks));
callbacks.Breakpoint = &Breakpoint;

err = jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks));
if (err != JVMTI_ERROR_NONE) {
return JNI_ERR;
}

return JNI_OK;
}

0 comments on commit 84f2f5e

Please sign in to comment.