1 /*
2  * Copyright (c) 2007, 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.unit.GetAllStackTraces;
25 
26 import java.io.PrintStream;
27 import nsk.share.Consts;
28 
29 public class getallstktr001 {
30 
31     final static int THREADS_LIMIT   = 40;
32     final static String NAME_PREFIX  = "getallstktr001-";
33     final static String THREAD_WAIT_METHOD_NAME = "RawMonitorEnter";
34 
GetResult()35     native static int  GetResult();
CreateRawMonitor()36     native static void CreateRawMonitor();
RawMonitorEnter()37     native static void RawMonitorEnter();
RawMonitorExit()38     native static void RawMonitorExit();
GetAllStackTraces()39     native static void GetAllStackTraces();
GetThreadsInfo()40     native static void GetThreadsInfo();
GetThreadListStackTraces()41     native static void GetThreadListStackTraces();
ForceGC()42     native static void ForceGC();
CompareStackTraces()43     native static void CompareStackTraces();
DeallocateBuffers()44     native static void DeallocateBuffers();
45 
46     static volatile int thrCount = 0;
47 
main(String args[])48     public static void main(String args[]) {
49         args = nsk.share.jvmti.JVMTITest.commonInit(args);
50 
51         // produce JCK-like exit status.
52         System.exit(run(args, System.out) + Consts.JCK_STATUS_BASE);
53     }
54 
run(String args[], PrintStream out)55     public static int run(String args[], PrintStream out) {
56         CreateRawMonitor();
57         TestThread thr[] = new TestThread[THREADS_LIMIT];
58 
59         RawMonitorEnter();
60 
61         for (int i=0; i < THREADS_LIMIT; i++) {
62             thr[i] = new TestThread(NAME_PREFIX + i);
63             thr[i].start();
64         }
65 
66         // Wait until all hreads reach the expected state.
67         TestThread.waitAll();
68 
69         // Now some of them have increased the counter,
70         // but may haven't reached RawMonitorEnter yet
71         // Wait for such threads to enter raw monitor
72         int tries = 100;
73         for ( ;; ) {
74             try { Thread.sleep(500); } catch ( InterruptedException e ) {}
75 
76             boolean allThreadsReady = true;
77             for ( Thread t : thr ) {
78                 StackTraceElement[] stack = t.getStackTrace();
79                 if ( stack.length == 0 ) {
80                     System.out.println("Thread " + t.getName() + " has an empty stack. Seems strange.");
81                     continue;
82                 }
83 
84                 if ( ! stack[0].getMethodName().equals(THREAD_WAIT_METHOD_NAME) ) {
85                     System.out.println("Thread " + t.getName() + " hasn't reached the raw monitor yet:");
86                     for ( StackTraceElement s : stack ) {
87                         System.out.println("\t" + s);
88                     }
89                     allThreadsReady = false;
90                     break;
91                 }
92             }
93 
94             if ( allThreadsReady )
95                 break;
96 
97             if ( --tries <= 0 )
98                 throw new Error("Timed out waiting for all threads reaching the raw monitor");
99         }
100 
101         GetAllStackTraces();
102         GetThreadsInfo();
103         GetThreadListStackTraces();
104         ForceGC();
105         CompareStackTraces();
106         DeallocateBuffers();
107 
108         RawMonitorExit();
109 
110         try {
111           for (int i=0; i < THREADS_LIMIT; i++) {
112               thr[i].join();
113           }
114 
115         } catch (InterruptedException e) {
116             throw new Error("Unexpected: " + e);
117         }
118         return GetResult();
119     }
120 
121     static class TestThread extends Thread {
122         static int counter=0;
123         int ind;
TestThread(String name)124         public TestThread(String name) {
125             super(name);
126         }
run()127         public void run() {
128             thrCount++;
129             foo(0);
130         }
incrCounter()131         private static synchronized void incrCounter() {
132            if (++counter == THREADS_LIMIT) {
133                TestThread.class.notify();
134            }
135         }
136 
waitAll()137         public static void waitAll() {
138            synchronized(TestThread.class) {
139                while (counter < THREADS_LIMIT) {
140                    try {
141                        TestThread.class.wait();
142                    } catch (InterruptedException ex) {
143                    }
144                }
145            }
146         }
147 
foo(int i)148         public void foo(int i) {
149             i++;
150             if ( i < 10 ) {
151                 foo(i);
152             } else {
153                 incrCounter();
154                 RawMonitorEnter();
155                 RawMonitorExit();
156             }
157 
158         }
159     }
160 }
161