1 /*
2  * Copyright (c) 2014, 2015, 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 compiler.testlibrary.rtm;
25 
26 import java.util.concurrent.BrokenBarrierException;
27 import java.util.concurrent.CyclicBarrier;
28 
29 /**
30  * Test case for busy lock scenario.
31  * One thread enters the monitor and sleep for a while.
32  * Another thread is blocked on the same monitor.
33  */
34 public class BusyLock implements CompilableTest, Runnable {
35     private static final int DEFAULT_TIMEOUT = 1000;
36     private final CyclicBarrier barrier;
37 
38     // Following field have to be static in order to avoid escape analysis.
39     @SuppressWarnings("UnsuedDeclaration")
40     private static int field = 0;
41     protected final Object monitor;
42     protected final int timeout;
43 
BusyLock()44     public BusyLock() {
45         this(BusyLock.DEFAULT_TIMEOUT);
46     }
47 
BusyLock(int timeout)48     public BusyLock(int timeout) {
49         this.timeout = timeout;
50         this.monitor = new Object();
51         this.barrier = new CyclicBarrier(2);
52     }
53 
54     @Override
run()55     public void run() {
56         try {
57             synchronized (monitor) {
58                 barrier.await();
59                 Thread.sleep(timeout);
60             }
61         } catch (InterruptedException | BrokenBarrierException e) {
62             throw new RuntimeException("Synchronization error happened.", e);
63         }
64     }
65 
syncAndTest()66     public void syncAndTest() {
67         try {
68             // wait until monitor is locked by a ::run method
69             barrier.await();
70         } catch (InterruptedException | BrokenBarrierException e) {
71             throw new RuntimeException("Synchronization error happened.", e);
72         }
73         test();
74     }
75 
test()76     public void test() {
77         synchronized(monitor) {
78             BusyLock.field++;
79         }
80     }
81 
82     @Override
getMethodWithLockName()83     public String getMethodWithLockName() {
84         return this.getClass().getName() + "::test";
85     }
86 
87     @Override
getMethodsToCompileNames()88     public String[] getMethodsToCompileNames() {
89         return new String[] { getMethodWithLockName() };
90     }
91 
92     /**
93      * Usage:
94      * BusyLock [ <inflate monitor> [ <timeout> ] ]
95      *
96      * Default values are:
97      * <ul>
98      *     <li>inflate monitor = {@code true}</li>
99      *     <li>timeout = {@code BusyLock.DEFAULT_TIMEOUT}</li>
100      * </ul>
101      */
main(String args[])102     public static void main(String args[]) throws Exception {
103         int timeoutValue = BusyLock.DEFAULT_TIMEOUT;
104         boolean inflateMonitor = true;
105 
106         if (args.length > 0 ) {
107             inflateMonitor = Boolean.valueOf(args[0]);
108 
109             if (args.length > 1) {
110                 timeoutValue = Integer.valueOf(args[1]);
111             }
112         }
113 
114         BusyLock busyLock = new BusyLock(timeoutValue);
115 
116         if (inflateMonitor) {
117             AbortProvoker.inflateMonitor(busyLock.monitor);
118         }
119 
120         Thread t = new Thread(busyLock);
121         t.start();
122         busyLock.syncAndTest();
123         t.join();
124     }
125 }
126