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