1 /*
2  * Copyright (c) 2000, 2018, 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
26  * @key stress
27  *
28  * @summary converted from VM testbase nsk/stress/thread/thread007.
29  * VM testbase keywords: [stress, diehard, slow, nonconcurrent, quick]
30  * VM testbase readme:
31  * DESCRIPTION
32  *     Try to start the given number of threads starting simultaneously
33  *     when notifyall() is signaled at the stopLine object.
34  *
35  * @run main/othervm nsk.stress.thread.thread007 500 2m 5s
36  */
37 
38 package nsk.stress.thread;
39 
40 import java.io.PrintStream;
41 
42 /**
43  * Try to start the given number of threads starting simultaneously
44  * when <code>notifyall()</code> is signaled at the <code>stopLine</code>
45  * object.
46  */
47 public class thread007 extends Thread {
48     /**
49      * Enable/disable printing of debugging info.
50      */
51     private static boolean DEBUG_MODE = false;
52 
53     /**
54      * The minimal number of threads that the tested JVM must support.
55      * (This number should be specified by the command-line parameter.
56      */
57     private static int THREADS_EXPECTED = 1000;
58 
59     /**
60      * Timeout (in milliseconds) after which all threads must halt.
61      */
62     private static long TIMEOUT = 300000; // 5 minutes
63 
64     /**
65      * Wait few seconds to allow child threads actually start.
66      */
67     private static long YIELD_TIME = 5000; // 5 seconds
68 
69     /**
70      * Once <code>arg</code> is ``XXXs'', or ``XXXm'', or ``XXXms'',
71      * return the given number of seconds, minutes, or milliseconds
72      * correspondingly.
73      */
parseTime(String arg)74     private static long parseTime(String arg) {
75         for (int i = arg.lastIndexOf("ms"); i > -1; )
76             return Long.parseLong(arg.substring(0, i));
77         for (int i = arg.lastIndexOf("s"); i > -1; )
78             return Long.parseLong(arg.substring(0, i)) * 1000;
79         for (int i = arg.lastIndexOf("m"); i > -1; )
80             return Long.parseLong(arg.substring(0, i)) * 60000;
81         throw new IllegalArgumentException(
82                 "cannot recognize time scale: " + arg);
83     }
84 
85     /**
86      * Re-invoke to <code>run(args,out)</code> in a JCK style.
87      */
main(String args[])88     public static void main(String args[]) {
89         int exitCode = run(args, System.out);
90         System.exit(exitCode + 95);
91     }
92 
93     /**
94      * Entry point for the JavaTest harness: <code>args[0]</code> must
95      * prescribe the value for the <code>THREADS_EXPECTED</code> field.
96      */
run(String args[], PrintStream out)97     public static int run(String args[], PrintStream out) {
98         if (args.length > 0)
99             THREADS_EXPECTED = Integer.parseInt(args[0]);
100         if (args.length > 1)
101             TIMEOUT = parseTime(args[1]);
102         if (args.length > 2)
103             YIELD_TIME = parseTime(args[2]);
104         if (args.length > 3)
105             DEBUG_MODE = args[3].toLowerCase().startsWith("-v");
106         if (args.length > 4) {
107             out.println("#");
108             out.println("# Too namy command-line arguments!");
109             out.println("#");
110             return 2;
111         }
112 
113         if (DEBUG_MODE) {
114             out.println("Start " + THREADS_EXPECTED + " threads,");
115             out.println("wait " + YIELD_TIME + " milliseconds to let them go,");
116             out.println("and halt after " + TIMEOUT + " milliseconds:");
117         }
118 
119         Thread thread[] = new Thread[THREADS_EXPECTED];
120         int i;
121         for (i = 0; i < THREADS_EXPECTED; i++)
122             try {
123                 thread[i] = new thread007();
124                 thread[i].start();
125                 if (DEBUG_MODE)
126                     out.println("Threads started: " + (i + 1));
127             } catch (OutOfMemoryError oome) {
128                 oome.printStackTrace(out);
129                 out.println("#");
130                 out.println("# The test have FAILED:");
131                 out.println("# Only " + i + " threads could start,");
132                 out.println("# while at least " + THREADS_EXPECTED +
133                         " were expected.");
134                 out.println("#");
135                 return 2;
136             }
137 
138         // Actually start:
139         synchronized (stopLine) {
140             stopLine.notifyAll();
141         }
142         // ...and let them go:
143         try {
144             doSleep(YIELD_TIME);
145         } catch (InterruptedException ie) {
146             ie.printStackTrace(out);
147             out.println("#");
148             out.println("# OOPS! Could not let threads actually start!");
149             out.println("#");
150             return 2;
151         }
152 
153         if (oopsCounter > 0) {
154             out.println("#");
155             out.println("# The test have FAILED, because:");
156             out.println("# " + oopsCounter + " threads were interrupted.");
157             out.println("#");
158             return 2;
159         }
160 
161         if (DEBUG_MODE)
162             out.println("The test have PASSED.");
163         return 0;
164     }
165 
166     static Object stopLine = new Object();
167     static int oopsCounter = 0;
168 
169     /**
170      * The thread activity: do nothing special, but do not
171      * free CPU time so that the thread's memory could not
172      * be moved to swap file.
173      */
run()174     public void run() {
175         synchronized (stopLine) {
176             try {
177                 stopLine.wait();
178             } catch (InterruptedException oops) {
179                 oopsCounter++;
180                 return;
181             }
182         }
183         while (!timeout())
184             continue;
185     }
186 
187     private static long startTime = System.currentTimeMillis();
188 
189     /**
190      * Check if timeout for this test is exceeded.
191      */
timeout()192     private boolean timeout() {
193         long elapsedTime = System.currentTimeMillis() - startTime;
194         return elapsedTime > TIMEOUT;
195     }
196 
197     /**
198      * Yield to other threads for the given amount of
199      * <code>time</code> (milliseconds).
200      */
doSleep(long time)201     private static void doSleep(long time) throws InterruptedException {
202         //
203         // Since Java 2, the method Thread.sleep() doesn't guarantee
204         // to yield to other threads. So, call Object.wait() to yield:
205         //
206         Object lock = new Object(); // local scope, nobody can notify it
207         synchronized (lock) {
208             lock.wait(time);
209         }
210     }
211 }
212