002de86081
Reviewed-by: amenkov, lmesnik, sspitsyn
138 lines
4.3 KiB
Java
138 lines
4.3 KiB
Java
/*
|
|
* Copyright (c) 2024, 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
|
|
* @bug 8340698
|
|
* @summary JVMTI FRAME_POP event is sometimes missed if NotifyFramePop is called as a method is returning
|
|
* @requires vm.jvmti
|
|
* @library /test/lib
|
|
* @compile NotifyFramePopStressTest.java
|
|
* @run main/othervm/native -agentlib:NotifyFramePopStressTest NotifyFramePopStressTest
|
|
*/
|
|
|
|
import jtreg.SkippedException;
|
|
|
|
public class NotifyFramePopStressTest {
|
|
static volatile boolean done = false;
|
|
|
|
public static void main(String args[]) {
|
|
if (!canGenerateFramePopEvents()) {
|
|
throw new SkippedException("FramePop event is not supported");
|
|
}
|
|
Thread testThread = Thread.currentThread();
|
|
Thread controlThread = new Thread(() -> control(testThread), "Control Thread");
|
|
|
|
setFramePopNotificationMode(testThread);
|
|
controlThread.start();
|
|
sleep(10);
|
|
|
|
for (int i = 0; i < 10*1000; i++) {
|
|
foo();
|
|
bar();
|
|
}
|
|
done = true;
|
|
|
|
try {
|
|
controlThread.join();
|
|
} catch (InterruptedException e) {
|
|
}
|
|
|
|
if (failed()) {
|
|
throw new RuntimeException("Test FAILED: see log for details");
|
|
} else {
|
|
log("Test PASSED");
|
|
}
|
|
}
|
|
|
|
private static void sleep(long ms) {
|
|
try {
|
|
Thread.sleep(ms);
|
|
} catch (InterruptedException e) {
|
|
}
|
|
}
|
|
|
|
private static void control(Thread thread) {
|
|
int notifyCount = 0;
|
|
|
|
log("control has started");
|
|
while (!done) {
|
|
suspend(thread);
|
|
if (done) {
|
|
// Double check after suspending the thread. We don't want to do the notify
|
|
// if the main thread thinks it is done. An untimely notify during the
|
|
// join() call will result in a deadlock.
|
|
resume(thread);
|
|
break;
|
|
}
|
|
if (notifyFramePop(thread)) {
|
|
notifyCount++;
|
|
log("control incremented notifyCount to " + notifyCount);
|
|
}
|
|
resume(thread);
|
|
int waitCount = 0;
|
|
while (notifyCount != getPopCount()) {
|
|
sleep(1);
|
|
waitCount++;
|
|
if (waitCount > 1000) {
|
|
break;
|
|
}
|
|
}
|
|
if (waitCount > 100) {
|
|
log("About to fail. notifyCount=" + notifyCount + " getPopCount()=" + getPopCount());
|
|
throw new RuntimeException("Test FAILED: Waited too long for notify: " + waitCount);
|
|
}
|
|
}
|
|
log("control has finished: " + notifyCount);
|
|
}
|
|
|
|
private native static void suspend(Thread thread);
|
|
private native static void resume(Thread thread);
|
|
private native static int getPopCount();
|
|
private native static boolean failed();
|
|
private native static boolean canGenerateFramePopEvents();
|
|
private native static void setFramePopNotificationMode(Thread thread);
|
|
private native static boolean notifyFramePop(Thread thread);
|
|
|
|
private static void log(String msg) {
|
|
System.out.println(msg);
|
|
}
|
|
|
|
private static int fetchIntFoo() {
|
|
return 13;
|
|
}
|
|
|
|
private static int fetchIntBar() {
|
|
return 33;
|
|
}
|
|
|
|
private static int foo() {
|
|
return fetchIntFoo();
|
|
}
|
|
|
|
private static int bar() {
|
|
return fetchIntBar();
|
|
}
|
|
}
|
|
|