1 /*
2  * Copyright (c) 2003, 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 package nsk.jvmti.scenarios.sampling.SP02;
25 
26 import java.io.PrintStream;
27 
28 import nsk.share.*;
29 import nsk.share.jvmti.*;
30 
31 public class sp02t003 extends DebugeeClass {
32 
33     // load native library if required
34     static {
35         System.loadLibrary("sp02t003");
36     }
37 
38     // run test from command line
main(String argv[])39     public static void main(String argv[]) {
40     argv = nsk.share.jvmti.JVMTITest.commonInit(argv);
41 
42     // JCK-compatible exit
43         System.exit(run(argv, System.out) + Consts.JCK_STATUS_BASE);
44     }
45 
46     // run test from JCK-compatible environment
run(String argv[], PrintStream out)47     public static int run(String argv[], PrintStream out) {
48         return new sp02t003().runIt(argv, out);
49     }
50 
51     /* =================================================================== */
52 
53     // scaffold objects
54     static public Log log = null;
55 
56     ArgumentHandler argHandler = null;
57     long timeout = 0;
58     int status = Consts.TEST_PASSED;
59 
60     // monitors for threads synchronization
61     static Object endingMonitor = new Object();
62 
63     // tested threads list
64     sp02t003Thread threads[] = null;
65 
66     // run debuggee
runIt(String argv[], PrintStream out)67     public int runIt(String argv[], PrintStream out) {
68         argHandler = new ArgumentHandler(argv);
69         log = new Log(out, argHandler);
70         timeout = argHandler.getWaitTime() * 60 * 1000; // milliseconds
71 
72         // create threads list
73         threads = new sp02t003Thread[] {
74             new sp02t003ThreadRunning("threadRunning"),
75             new sp02t003ThreadEntering("threadEntering"),
76             new sp02t003ThreadWaiting("threadWaiting"),
77             new sp02t003ThreadSleeping("threadSleeping"),
78             new sp02t003ThreadRunningInterrupted("threadRunningInterrupted"),
79             new sp02t003ThreadRunningNative("threadRunningNative")
80         };
81 
82         // run threads
83         log.display("Starting tested threads");
84         try {
85             synchronized (endingMonitor) {
86                 // start threads (except first one)
87                 for (int i = 0; i < threads.length; i++) {
88                     synchronized (threads[i].startingMonitor) {
89                         threads[i].start();
90                         threads[i].startingMonitor.wait();
91                     }
92                     if (!threads[i].checkReady()) {
93                         throw new Failure("Unable to prepare thread #" + i + ": " + threads[i]);
94                     }
95                 }
96 
97                 // testing sync
98             log.display("Testing sync: threads ready");
99                 status = checkStatus(status);
100             }
101         } catch (InterruptedException e) {
102             throw new Failure(e);
103         } finally {
104             // let all threads to finish
105             for (int i = 0; i < threads.length; i++) {
106                 threads[i].letFinish();
107             }
108         }
109 
110         // wait for all threads to finish
111         log.display("Finishing tested threads");
112         try {
113             for (int i = 0; i < threads.length; i++) {
114                 threads[i].join();
115             }
116         } catch (InterruptedException e) {
117             throw new Failure(e);
118         }
119 
120         return status;
121     }
122 }
123 
124 /* =================================================================== */
125 
126 // basic class for tested threads
127 abstract class sp02t003Thread extends Thread {
128     public Object startingMonitor = new Object();
129 
130     // make thread with specific name
sp02t003Thread(String name)131     public sp02t003Thread(String name) {
132         super(name);
133     }
134 
135     // tested method
testedMethod()136     public abstract void testedMethod();
137 
138     // run thread and call tested method
run()139     public void run() {
140         // call tested mathod
141         sp02t003.log.display(getName() + ": run(): before call to testedMethod");
142         testedMethod();
143         sp02t003.log.display(getName() + ": run():  after call to testedMethod");
144     }
145 
146     // check if thread is ready for testing
checkReady()147     public boolean checkReady() {
148         // return true by default
149         return true;
150     }
151 
152     // let thread to finish
letFinish()153     public void letFinish() {
154         // do nothing by default
155     }
156 }
157 
158 /* =================================================================== */
159 
160 class sp02t003ThreadRunning extends sp02t003Thread {
161     private volatile boolean shouldFinish = false;
162 
sp02t003ThreadRunning(String name)163     public sp02t003ThreadRunning(String name) {
164         super(name);
165     }
166 
testedMethod()167     public void testedMethod() {
168         sp02t003.log.display(getName() + ": testedMethod()");
169 
170         // notify about starting
171         synchronized (startingMonitor) {
172             startingMonitor.notifyAll();
173         }
174 
175         // run in a loop
176         int i = 0;
177         int n = 1000;
178         while (!shouldFinish) {
179             if (n <= 0) {
180                 n = 1000;
181             }
182             if (i > n) {
183                 i = 0;
184                 n = n - 1;
185             }
186             i = i + 1;
187         }
188     }
189 
letFinish()190     public void letFinish() {
191         shouldFinish = true;
192     }
193 }
194 
195 class sp02t003ThreadEntering extends sp02t003Thread {
sp02t003ThreadEntering(String name)196     public sp02t003ThreadEntering(String name) {
197         super(name);
198     }
199 
testedMethod()200     public void testedMethod() {
201         sp02t003.log.display(getName() + ": testedMethod()");
202 
203         // notify about starting
204         synchronized (startingMonitor) {
205             startingMonitor.notifyAll();
206         }
207 
208         // wait for endingMonitor to become released
209         synchronized (sp02t003.endingMonitor) {
210             // do nothing
211         }
212     }
213 }
214 
215 class sp02t003ThreadWaiting extends sp02t003Thread {
216     private Object waitingMonitor = new Object();
217 
sp02t003ThreadWaiting(String name)218     public sp02t003ThreadWaiting(String name) {
219         super(name);
220     }
221 
testedMethod()222     public void testedMethod() {
223         sp02t003.log.display(getName() + ": testedMethod()");
224 
225         synchronized (waitingMonitor) {
226 
227             // notify about starting
228             synchronized (startingMonitor) {
229                 startingMonitor.notifyAll();
230             }
231 
232             // wait on monitor
233             try {
234                 waitingMonitor.wait();
235             } catch (InterruptedException ignore) {
236                 // just finish
237             }
238         }
239     }
240 
checkReady()241     public boolean checkReady() {
242         // wait until waitingMonitor released on wait()
243         synchronized (waitingMonitor) {
244         }
245         return true;
246     }
247 
letFinish()248     public void letFinish() {
249         synchronized (waitingMonitor) {
250             waitingMonitor.notifyAll();
251         }
252     }
253 }
254 
255 class sp02t003ThreadSleeping extends sp02t003Thread {
sp02t003ThreadSleeping(String name)256     public sp02t003ThreadSleeping(String name) {
257         super(name);
258     }
259 
testedMethod()260     public void testedMethod() {
261         sp02t003.log.display(getName() + ": testedMethod()");
262 
263         // sleep for a loooong time
264         long timeout = 7 * 24 * 60 * 60 * 1000; // one week in milliseconds
265 
266         // notify about starting
267         synchronized (startingMonitor) {
268             startingMonitor.notifyAll();
269         }
270 
271         try {
272             sleep(timeout);
273         } catch (InterruptedException ignore) {
274             // just finish
275         }
276     }
277 
letFinish()278     public void letFinish() {
279         interrupt();
280     }
281 }
282 
283 class sp02t003ThreadRunningInterrupted extends sp02t003Thread {
284     private Object waitingMonitor = new Object();
285     private volatile boolean shouldFinish = false;
286 
sp02t003ThreadRunningInterrupted(String name)287     public sp02t003ThreadRunningInterrupted(String name) {
288         super(name);
289     }
290 
testedMethod()291     public void testedMethod() {
292         sp02t003.log.display(getName() + ": testedMethod()");
293 
294         synchronized (waitingMonitor) {
295 
296             // notify about starting
297             synchronized (startingMonitor) {
298                 startingMonitor.notifyAll();
299             }
300 
301             // wait on watingMonitor until interrupted
302             try {
303                 waitingMonitor.wait();
304             } catch (InterruptedException ignore) {
305                 // just continue
306             }
307         }
308 
309         // run in a loop
310         int i = 0;
311         int n = 1000;
312         while (!shouldFinish) {
313             if (n <= 0) {
314                 n = 1000;
315             }
316             if (i > n) {
317                 i = 0;
318                 n = n - 1;
319             }
320             i = i + 1;
321         }
322     }
323 
checkReady()324     public boolean checkReady() {
325         // interrupt thread on wait()
326         synchronized (waitingMonitor) {
327             interrupt();
328         }
329 
330         return true;
331     }
332 
letFinish()333     public void letFinish() {
334         shouldFinish = true;
335     }
336 }
337 
338 class sp02t003ThreadRunningNative extends sp02t003Thread {
sp02t003ThreadRunningNative(String name)339     public sp02t003ThreadRunningNative(String name) {
340         super(name);
341     }
342 
run()343     public void run() {
344         // notify about starting
345         synchronized (startingMonitor) {
346             startingMonitor.notifyAll();
347         }
348 
349         // call tested mathod
350         sp02t003.log.display(getName() + ": run(): before call to testedMethod");
351         testedMethod();
352         sp02t003.log.display(getName() + ": run():  after call to testedMethod");
353     }
354 
testedMethod()355     public native void testedMethod();
356 
checkReady()357     public native boolean checkReady();
letFinish()358     public native void letFinish();
359 }
360