1 /*
  2  * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 /*
 25  * @test id=default
 26  * @summary Test SuspendThread/ResumeThread, SuspendThreadList/ResumeThreadList
 27  *          for virtual threads.
 28  * @library /test/lib
 29  * @compile SuspendResume1.java
 30  * @run driver jdk.test.lib.FileInstaller . .
 31  * @run main/othervm/native/timeout=600
 32  *      -Djdk.virtualThreadScheduler.maxPoolSize=1
 33  *      -agentlib:SuspendResume1
 34  *      SuspendResume1
 35  */
 36 
 37  /*
 38  * @test id=no-vmcontinuations
 39  * @requires vm.continuations
 40  * @library /test/lib
 41  * @compile SuspendResume1.java
 42  * @run driver jdk.test.lib.FileInstaller . .
 43  * @run main/othervm/native/timeout=600
 44  *      -agentlib:SuspendResume1
 45  *      -XX:+UnlockExperimentalVMOptions
 46  *      -XX:-VMContinuations
 47  *      SuspendResume1
 48  */
 49 
 50 import java.io.PrintStream;
 51 import java.util.concurrent.*;
 52 import jdk.test.lib.jvmti.DebugeeClass;
 53 
 54 public class SuspendResume1 extends DebugeeClass {
 55 
 56     // load native library if required
 57     static {
 58         System.loadLibrary("SuspendResume1");
 59     }
 60 
 61     native static void TestSuspendResume();
 62     native static int GetStatus();
 63 
 64     static public void sleep(long millis) {
 65         try {
 66             Thread.sleep(millis);
 67         } catch (InterruptedException e) {
 68             throw new RuntimeException("Interruption in TestedThread.sleep: \n\t" + e);
 69         }
 70     }
 71 
 72     // run test from command line
 73     public static void main(String argv[]) {
 74         int status = run(argv, System.out);
 75         if (status != DebugeeClass.TEST_PASSED) {
 76             throw new RuntimeException("FAILED: unexpected status: " + status);
 77         }
 78     }
 79 
 80     public static int run(String argv[], PrintStream out) {
 81         return new SuspendResume1().runIt(argv, out);
 82     }
 83 
 84     private static final int VTHREADS_CNT = 20;
 85     int status = DebugeeClass.TEST_PASSED;
 86 
 87     // run debuggee
 88     public int runIt(String argv[], PrintStream out) {
 89         System.out.println("\n## Java: runIt: Starting threads");
 90         status = test_vthreads();
 91         if (status != DebugeeClass.TEST_PASSED) {
 92             System.out.println("\n## Java: runIt FAILED: status from native Agent: " + status);
 93         }
 94         return status;
 95     }
 96 
 97     private int test_vthreads() {
 98         TestedThread[] threads = new TestedThread[VTHREADS_CNT];
 99         Thread vts[] = new Thread[VTHREADS_CNT];
100 
101         for (int i = 0; i < VTHREADS_CNT; i++) {
102             String name = "TestedThread" + i;
103             TestedThread thread = new TestedThread(name);
104             threads[i] = thread;
105             vts[i] = start_thread(name, thread);
106         }
107 /*
108         status = checkStatus(status);
109         if (status != DebugeeClass.TEST_PASSED) {
110             return status;
111         }
112 */
113         System.out.println("\n## Java: runIt: testing Suspend/Resume");
114         TestSuspendResume();
115 
116         System.out.println("\n## Java: runIt: Finishing vthreads");
117         try {
118             for (int i = 0; i < VTHREADS_CNT; i++) {
119                 // let thread to finish
120                 TestedThread thread = threads[i];
121                 thread.letFinish();
122                 vts[i].join();
123             }
124         } catch (InterruptedException e) {
125             throw new RuntimeException(e);
126         }
127         return GetStatus();
128     }
129 
130     Thread start_thread(String name, TestedThread thread) {
131         Thread vthread =  Thread.ofVirtual().name(name).start(thread);
132         thread.ensureReady(); // testing sync
133         System.out.println("## Java: started thread: " + name);
134         return vthread;
135     }
136 }
137 
138 // class for tested threads
139 class TestedThread extends Thread {
140     private volatile boolean threadReady = false;
141     private volatile boolean shouldFinish = false;
142 
143     // make thread with specific name
144     public TestedThread(String name) {
145         super(name);
146     }
147 
148     // run thread continuously
149     public void run() {
150         // run in a loop
151         threadReady = true;
152         int i = 0;
153         int n = 1000;
154         while (!shouldFinish) {
155             if (n <= 0) {
156                 n = 1000;
157                 SuspendResume1.sleep(10);
158             }
159             if (i > n) {
160                 i = 0;
161                 n = n - 1;
162             }
163             i = i + 1;
164         }
165     }
166 
167     // ensure thread is ready
168     public void ensureReady() {
169         try {
170             while (!threadReady) {
171                 sleep(1000);
172             }
173         } catch (InterruptedException e) {
174             throw new RuntimeException("Interruption while preparing tested thread: \n\t" + e);
175         }
176     }
177 
178     // let thread to finish
179     public void letFinish() {
180         shouldFinish = true;
181     }
182 }