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 SuspendAllVirtualThreads/ResumeAllVirtualThreads
 27  * @library /test/lib
 28  * @compile SuspendResume2.java
 29  * @run driver jdk.test.lib.FileInstaller . .
 30  * @run main/othervm/native
 31  *      -Djdk.virtualThreadScheduler.maxPoolSize=1
 32  *      -agentlib:SuspendResume2
 33  *      SuspendResume2
 34  */
 35 
 36 /*
 37  * @test id=no-vmcontinuations
 38  * @requires vm.continuations
 39  * @library /test/lib
 40  * @compile SuspendResume2.java
 41  * @run driver jdk.test.lib.FileInstaller . .
 42  * @run main/othervm/native
 43  *      -agentlib:SuspendResume2
 44  *      -XX:+UnlockExperimentalVMOptions
 45  *      -XX:-VMContinuations
 46  *      SuspendResume2
 47  */
 48 
 49 import java.io.PrintStream;
 50 import java.util.concurrent.*;
 51 import jdk.test.lib.jvmti.DebugeeClass;
 52 
 53 public class SuspendResume2 extends DebugeeClass {
 54 
 55     // load native library if required
 56     static {
 57         System.loadLibrary("SuspendResume2");
 58     }
 59 
 60     native static void TestSuspendResume();
 61     native static int GetStatus();
 62 
 63     static public void sleep(long millis) {
 64         try {
 65             Thread.sleep(millis);
 66         } catch (InterruptedException e) {
 67             throw new RuntimeException("Interruption in TestedThread.sleep: \n\t" + e);
 68         }
 69     }
 70 
 71     // run test from command line
 72     public static void main(String argv[]) {
 73         int status = run(argv, System.out);
 74         if (status != DebugeeClass.TEST_PASSED) {
 75             throw new RuntimeException("FAILED: unexpected status: " + status);
 76         }
 77     }
 78 
 79     public static int run(String argv[], PrintStream out) {
 80         return new SuspendResume2().runIt(argv, out);
 81     }
 82 
 83     private static final int VTHREADS_CNT = 20;
 84     int status = DebugeeClass.TEST_PASSED;
 85 
 86     // run debuggee
 87     public int runIt(String argv[], PrintStream out) {
 88         System.out.println("\n## Java: runIt: Starting threads");
 89         status = test_vthreads();
 90         if (status != DebugeeClass.TEST_PASSED) {
 91             System.out.println("\n## Java: runIt FAILED: status from native Agent: " + status);
 92         }
 93         return status;
 94     }
 95 
 96     private int test_vthreads() {
 97         TestedThread[] threads = new TestedThread[VTHREADS_CNT];
 98         Thread vts[] = new Thread[VTHREADS_CNT];
 99 
100         for (int i = 0; i < VTHREADS_CNT; i++) {
101             String name = "TestedThread" + i;
102             TestedThread thread = new TestedThread(name);
103             threads[i] = thread;
104             vts[i] = start_thread(name, thread);
105         }
106 
107         System.out.println("\n## Java: runIt: testing Suspend/Resume");
108         TestSuspendResume();
109 
110         System.out.println("\n## Java: runIt: Finishing vthreads");
111         try {
112             for (int i = 0; i < VTHREADS_CNT; i++) {
113                 // let thread to finish
114                 TestedThread thread = threads[i];
115                 thread.letFinish();
116                 vts[i].join();
117             }
118         } catch (InterruptedException e) {
119             throw new RuntimeException(e);
120         }
121         return GetStatus();
122     }
123 
124     Thread start_thread(String name, TestedThread thread) {
125         Thread vthread =  Thread.ofVirtual().name(name).start(thread);
126         thread.ensureReady(); // testing sync
127         System.out.println("## Java: started thread: " + name);
128         return vthread;
129     }
130 }
131 
132 // class for tested threads
133 class TestedThread extends Thread {
134     private volatile boolean threadReady = false;
135     private volatile boolean shouldFinish = false;
136 
137     // make thread with specific name
138     public TestedThread(String name) {
139         super(name);
140     }
141 
142     // run thread continuously
143     public void run() {
144         // run in a loop
145         threadReady = true;
146         int i = 0;
147         int n = 1000;
148         while (!shouldFinish) {
149             if (n <= 0) {
150                 n = 1000;
151                 SuspendResume2.sleep(1);
152             }
153             if (i > n) {
154                 i = 0;
155                 n = n - 1;
156             }
157             i = i + 1;
158         }
159     }
160 
161     // ensure thread is ready
162     public void ensureReady() {
163         try {
164             while (!threadReady) {
165                 sleep(1);
166             }
167         } catch (InterruptedException e) {
168             throw new RuntimeException("Interruption while preparing tested thread: \n\t" + e);
169         }
170     }
171 
172     // let thread to finish
173     public void letFinish() {
174         shouldFinish = true;
175     }
176 }