Path: blob/master/test/hotspot/jtreg/serviceability/jvmti/SuspendWithCurrentThread/SuspendWithCurrentThread.java
41155 views
/*1* Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/*24* @test25* @bug 823159526* @summary [TEST] develop a test case for SuspendThreadList including current thread27* @requires vm.jvmti28* @library /test/lib29* @compile SuspendWithCurrentThread.java30* @run main/othervm/native -agentlib:SuspendWithCurrentThread SuspendWithCurrentThread SuspenderIndex=first31* @run main/othervm/native -agentlib:SuspendWithCurrentThread SuspendWithCurrentThread SuspenderIndex=last32*/3334import java.io.PrintStream;3536public class SuspendWithCurrentThread {37private static final String AGENT_LIB = "SuspendWithCurrentThread";38private static final String SUSPENDER_OPT = "SuspenderIndex=";39private static final int THREADS_COUNT = 10;4041private static void log(String msg) { System.out.println(msg); }4243private static native void registerTestedThreads(Thread[] threads);44private static native boolean checkTestedThreadsSuspended();45private static native void resumeTestedThreads();46private static native void releaseTestedThreadsInfo();4748// The suspender thread index defines the thread which has to suspend49// the tested threads including itself with the JVMTI SuspendThreadList50private static int suspenderIndex;5152public static void main(String args[]) throws Exception {53try {54System.loadLibrary(AGENT_LIB);55log("Loaded library: " + AGENT_LIB);56} catch (UnsatisfiedLinkError ule) {57log("Failed to load library: " + AGENT_LIB);58log("java.library.path: " + System.getProperty("java.library.path"));59throw ule;60}61if (args.length != 1) {62throw new RuntimeException("Main: wrong arguments count: " + args.length + ", expected: 1");63}64String arg = args[0];65if (arg.equals(SUSPENDER_OPT + "first")) {66suspenderIndex = 0;67} else if (arg.equals(SUSPENDER_OPT + "last")) {68suspenderIndex = THREADS_COUNT - 1;69} else {70throw new RuntimeException("Main: wrong argument: " + arg + ", expected: SuspenderIndex={first|last}");71}72log("Main: suspenderIndex: " + suspenderIndex);7374SuspendWithCurrentThread test = new SuspendWithCurrentThread();75test.run();76}7778private ThreadToSuspend[] startTestedThreads(int threadsCount) throws RuntimeException {79ThreadToSuspend[]threads = new ThreadToSuspend[threadsCount];8081// create tested threads82for (int i = 0; i < threads.length; i++) {83threads[i] = new ThreadToSuspend("ThreadToSuspend#" + i,84i == suspenderIndex // isSuspender85);86}87log("Main: starting tested threads");88for (int i = 0; i < threads.length; i++) {89threads[i].start();90if (!threads[i].checkReady()) {91throw new RuntimeException("Main: unable to prepare tested thread: " + threads[i]);92}93}94log("Main: tested threads started");9596registerTestedThreads(threads);97return threads;98}99100private boolean checkSuspendedStatus() throws RuntimeException {101log("Main: checking all tested threads have been suspended");102return checkTestedThreadsSuspended();103}104105/* The test does the following steps:106* - main thread starts several (THREADS_COUNT) ThreadToSuspend tested threads107* - main thread waits for threads to be ready with the thread.checkReady()108* - main thread registers tested threads within the native agent library109* with the native method registerTestedThreads()110* - main thread triggers the suspender tested thread with the111* ThreadToSuspend.setAllThreadsReady() to suspend tested threads112* - suspender thread suspends tested threads including itself with the native113* method suspendTestedThreads() (uses the JVMTI SuspendThreadList function)114* - main thread checks tested threads suspended status with the native method115* checkSuspendedStatus(); the tested threads are expected to have suspended status116* - main thread resumes tested threads with the native method resumeTestedThreads()117* - main thread releases tested threads with the native method releaseTestedThreads()118* - main thread triggers the tested threads to finish with the thread.letFinish()119*/120private void run() throws Exception {121ThreadToSuspend[] threads = null; // tested threads122123log("Main: started");124try {125threads = startTestedThreads(THREADS_COUNT);126127log("Main: trigger " + threads[suspenderIndex].getName() +128" to suspend all tested threads including itself");129ThreadToSuspend.setAllThreadsReady();130131while (!checkSuspendedStatus()) {132Thread.sleep(10);133}134135log("Main: resuming all tested threads");136resumeTestedThreads();137} finally {138// let threads to finish139for (int i = 0; i < threads.length; i++) {140threads[i].letFinish();141}142log("Main: tested threads finished");143}144145// wait for threads to finish146log("Main: joining tested threads");147try {148for (int i = 0; i < threads.length; i++) {149threads[i].join();150}151log("Main: tested thread joined");152} catch (InterruptedException e) {153throw new RuntimeException(e);154}155log("Main: releasing tested threads native info");156releaseTestedThreadsInfo();157158log("Main: finished");159}160}161162/* =================================================================== */163164// tested threads165class ThreadToSuspend extends Thread {166private static void log(String msg) { System.out.println(msg); }167168private static native void suspendTestedThreads();169private static volatile boolean allThreadsReady = false;170171public static void setAllThreadsReady() {172allThreadsReady = true;173}174175private volatile boolean threadReady = false;176private volatile boolean shouldFinish = false;177private boolean isSuspender = false;178179// make thread with specific name180public ThreadToSuspend(String name, boolean isSuspender) {181super(name);182this.isSuspender = isSuspender;183}184185// run thread continuously186public void run() {187boolean needSuspend = true;188threadReady = true;189190// run in a loop191while (!shouldFinish) {192if (isSuspender && needSuspend && allThreadsReady) {193log(getName() + ": before suspending all tested threads including myself");194needSuspend = false;195suspendTestedThreads();196log(getName() + ": after suspending all tested threads including myself");197}198}199}200201// check if thread is ready202public boolean checkReady() {203try {204while (!threadReady) {205sleep(1);206}207} catch (InterruptedException e) {208throw new RuntimeException("checkReady: sleep was interrupted\n\t" + e);209}210return threadReady;211}212213// let thread to finish214public void letFinish() {215shouldFinish = true;216}217}218219220