1 /*
  2  * Copyright Amazon.com Inc. 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 import jdk.test.lib.process.OutputAnalyzer;
 25 import jdk.test.lib.process.ProcessTools;
 26 
 27 import java.util.ArrayList;
 28 import java.util.Arrays;
 29 import java.util.List;
 30 
 31 /*
 32  * @test id=defaults
 33  * @bug 8319048
 34  * @summary Test the MonitorUnlinkBatch options
 35  * @library /test/lib
 36  * @run driver MonitorUnlinkBatchTest defaults
 37  */
 38 
 39 /*
 40  * @test id=legal
 41  * @library /test/lib
 42  * @run driver MonitorUnlinkBatchTest legal
 43  */
 44 
 45 /*
 46  * @test id=illegal
 47  * @library /test/lib
 48  * @run driver MonitorUnlinkBatchTest illegal
 49  */
 50 
 51 /*
 52  * @test id=aggressive
 53  * @library /test/lib
 54  * @run driver MonitorUnlinkBatchTest aggressive
 55  */
 56 
 57 /*
 58  * @test id=lazy
 59  * @library /test/lib
 60  * @run driver MonitorUnlinkBatchTest lazy
 61  */
 62 
 63 
 64 public class MonitorUnlinkBatchTest {
 65 
 66     public static class Test {
 67         // Inflate a lot of monitors, so that threshold heuristics definitely fires
 68         private static final int MONITORS = 10_000;
 69 
 70         // Use a handful of threads to inflate the monitors, to eat the cost of
 71         // wait(1) calls. This can be larger than available parallelism, since threads
 72         // would be time-waiting.
 73         private static final int THREADS = 16;
 74 
 75         private static Thread[] threads;
 76         private static Object[] monitors;
 77 
 78         public static void main(String... args) throws Exception {
 79             monitors = new Object[MONITORS];
 80             threads = new Thread[THREADS];
 81 
 82             for (int t = 0; t < THREADS; t++) {
 83                 int monStart = t * MONITORS / THREADS;
 84                 int monEnd = (t + 1) * MONITORS / THREADS;
 85                 threads[t] = new Thread(() -> {
 86                     for (int m = monStart; m < monEnd; m++) {
 87                         Object o = new Object();
 88                         synchronized (o) {
 89                             try {
 90                                 o.wait(1);
 91                             } catch (InterruptedException e) {
 92                             }
 93                         }
 94                         monitors[m] = o;
 95                     }
 96                 });
 97                 threads[t].start();
 98             }
 99 
100             for (Thread t : threads) {
101                 t.join();
102             }
103 
104             try {
105                 Thread.sleep(10_000);
106             } catch (InterruptedException ie) {
107             }
108         }
109     }
110 
111     public static void main(String[] args) throws Exception {
112         if (args.length < 1) {
113             throw new IllegalArgumentException("Expect the test label");
114         }
115 
116         String test = args[0];
117         switch (test) {
118             case "defaults":
119                 test("");
120                 break;
121 
122             case "legal":
123                 // Legal, even if not useful settings
124                 test("",
125                      "-XX:MonitorDeflationMax=100000",
126                      "-XX:MonitorUnlinkBatch=100001"
127                      );
128                 break;
129 
130             case "illegal":
131                 // Quick tests that should fail on JVM flags verification.
132                 test("outside the allowed range",
133                      "-XX:MonitorUnlinkBatch=-1"
134                 );
135                 test("outside the allowed range",
136                      "-XX:MonitorUnlinkBatch=0"
137                 );
138                 break;
139 
140             case "aggressive":
141                 // The smallest batch possible.
142                 test("",
143                      "-XX:MonitorUnlinkBatch=1"
144                 );
145                 break;
146 
147             case "lazy":
148                 // The largest batch possible.
149                 test("",
150                      "-XX:MonitorDeflationMax=1000000",
151                      "-XX:MonitorUnlinkBatch=1000000"
152                 );
153                 break;
154 
155             default:
156                 throw new IllegalArgumentException("Unknown test: " + test);
157         }
158     }
159 
160     public static void test(String msg, String... args) throws Exception {
161         List<String> opts = new ArrayList<>();
162         opts.add("-Xmx128M");
163         opts.add("-XX:+UnlockDiagnosticVMOptions");
164         opts.add("-XX:GuaranteedAsyncDeflationInterval=100");
165         opts.addAll(Arrays.asList(args));
166         opts.add("MonitorUnlinkBatchTest$Test");
167 
168         ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(opts);
169         OutputAnalyzer oa = new OutputAnalyzer(pb.start());
170         if (msg.isEmpty()) {
171             oa.shouldHaveExitValue(0);
172         } else {
173             oa.shouldNotHaveExitValue(0);
174             oa.shouldContain(msg);
175         }
176     }
177 
178 }