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 package rtm;
26
27 import java.util.Objects;
28 import java.util.concurrent.BrokenBarrierException;
29 import java.util.concurrent.CyclicBarrier;
30
31 import com.oracle.java.testlibrary.Asserts;
32 import com.oracle.java.testlibrary.Utils;
33 import sun.misc.Unsafe;
34
35 /**
36 * Base class for different transactional execution abortion
37 * provokers aimed to force abort due to specified reason.
38 */
39 public abstract class AbortProvoker implements CompilableTest {
40 public static final long DEFAULT_ITERATIONS = 10000L;
41 /**
42 * Inflates monitor associated with object {@code monitor}.
43 * Inflation is forced by entering the same monitor from
44 * two different threads.
45 *
46 * @param monitor monitor to be inflated.
47 * @return inflated monitor.
48 * @throws Exception if something went wrong.
49 */
50 public static Object inflateMonitor(Object monitor) throws Exception {
51 Unsafe unsafe = Utils.getUnsafe();
52 CyclicBarrier barrier = new CyclicBarrier(2);
53
54 Runnable inflatingRunnable = () -> {
55 unsafe.monitorEnter(monitor);
56 try {
57 barrier.await();
58 barrier.await();
59 } catch (InterruptedException | BrokenBarrierException e) {
60 throw new RuntimeException(
61 "Synchronization issue occurred.", e);
62 } finally {
63 unsafe.monitorExit(monitor);
64 }
65 };
66
67 Thread t = new Thread(inflatingRunnable);
68 t.start();
69 // Wait until thread t enters the monitor.
70 barrier.await();
71 // At this point monitor will be owned by thread t,
72 // so our attempt to enter the same monitor will force
73 // monitor inflation.
74 Asserts.assertFalse(unsafe.tryMonitorEnter(monitor),
75 "Not supposed to enter the monitor first");
76 barrier.await();
77 t.join();
78 return monitor;
79 }
80
81
82 /**
83 * Get instance of specified AbortProvoker, inflate associated monitor
84 * if needed and then invoke forceAbort method in a loop.
85 *
86 * Usage:
87 * AbortProvoker <AbortType name> [<inflate monitor>
88 * [<iterations> [ <delay>]]]
89 *
90 * Default parameters are:
91 * <ul>
92 * <li>inflate monitor = <b>true</b></li>
93 * <li>iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}</li>
94 * <li>delay = <b>0</b></li>
95 * </ul>
96 */
97 public static void main(String args[]) throws Throwable {
98 Asserts.assertGT(args.length, 0, "At least one argument is required.");
99
100 AbortType abortType = AbortType.lookup(Integer.valueOf(args[0]));
103
104 if (args.length > 1) {
105 monitorShouldBeInflated = Boolean.valueOf(args[1]);
106
107 if (args.length > 2) {
108 iterations = Long.valueOf(args[2]);
109
110 if (args.length > 3) {
111 Thread.sleep(Integer.valueOf(args[3]));
112 }
113 }
114 }
115
116 AbortProvoker provoker = abortType.provoker();
117
118 if (monitorShouldBeInflated) {
119 provoker.inflateMonitor();
120 }
121
122 for (long i = 0; i < iterations; i++) {
123 provoker.forceAbort();
124 }
125 }
126
127 protected final Object monitor;
128
129 protected AbortProvoker() {
130 this(new Object());
131 }
132
133 protected AbortProvoker(Object monitor) {
134 this.monitor = Objects.requireNonNull(monitor);
135 }
136
137 /**
138 * Inflates monitor used by this AbortProvoker instance.
139 * @throws Exception
140 */
141 public void inflateMonitor() throws Exception {
142 AbortProvoker.inflateMonitor(monitor);
|
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 package rtm;
26
27 import java.util.Objects;
28 import java.util.concurrent.BrokenBarrierException;
29 import java.util.concurrent.CyclicBarrier;
30
31 import com.oracle.java.testlibrary.Asserts;
32 import sun.hotspot.WhiteBox;
33
34 /**
35 * Base class for different transactional execution abortion
36 * provokers aimed to force abort due to specified reason.
37 */
38 public abstract class AbortProvoker implements CompilableTest {
39 public static final long DEFAULT_ITERATIONS = 10000L;
40 private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
41 @SuppressWarnings("unused")
42 private static int sharedState = 0;
43 /**
44 * Inflates monitor associated with object {@code monitor}.
45 * Inflation is forced by entering the same monitor from
46 * two different threads.
47 *
48 * @param monitor monitor to be inflated.
49 * @return inflated monitor.
50 * @throws Exception if something went wrong.
51 */
52 public static Object inflateMonitor(Object monitor) throws Exception {
53 CyclicBarrier barrier = new CyclicBarrier(2);
54
55 Runnable inflatingRunnable = () -> {
56 synchronized (monitor) {
57 try {
58 barrier.await();
59 } catch (BrokenBarrierException | InterruptedException e) {
60 throw new RuntimeException(
61 "Synchronization issue occurred.", e);
62 }
63 try {
64 monitor.wait();
65 } catch (InterruptedException e) {
66 throw new AssertionError("The thread waiting on an"
67 + " inflated monitor was interrupted, thus test"
68 + " results may be incorrect.", e);
69 }
70 }
71 };
72
73 Thread t = new Thread(inflatingRunnable);
74 t.setDaemon(true);
75 t.start();
76 // Wait until thread t enters the monitor.
77 barrier.await();
78 synchronized (monitor) {
79 // At this point thread t is already waiting on the monitor.
80 // Modifying static field just to avoid lock's elimination.
81 sharedState++;
82 }
83 verifyMonitorState(monitor, true /* inflated */);
84 return monitor;
85 }
86
87 /**
88 * Verifies that {@code monitor} is a stack-lock or inflated lock depending
89 * on {@code shouldBeInflated} value. If {@code monitor} is inflated while
90 * it is expected that it should be a stack-lock, then this method attempts
91 * to deflate it by forcing a safepoint and then verifies the state once
92 * again.
93 *
94 * @param monitor monitor to be verified.
95 * @param shouldBeInflated flag indicating whether or not monitor is
96 * expected to be inflated.
97 * @throws RuntimeException if the {@code monitor} in a wrong state.
98 */
99 public static void verifyMonitorState(Object monitor,
100 boolean shouldBeInflated) {
101 if (!shouldBeInflated && WHITE_BOX.isMonitorInflated(monitor)) {
102 WHITE_BOX.forceSafepoint();
103 }
104 Asserts.assertEQ(WHITE_BOX.isMonitorInflated(monitor), shouldBeInflated,
105 "Monitor in a wrong state.");
106 }
107 /**
108 * Verifies that monitor used by the {@code provoker} is a stack-lock or
109 * inflated lock depending on {@code shouldBeInflated} value. If such
110 * monitor is inflated while it is expected that it should be a stack-lock,
111 * then this method attempts to deflate it by forcing a safepoint and then
112 * verifies the state once again.
113 *
114 * @param provoker AbortProvoker whose monitor's state should be verified.
115 * @param shouldBeInflated flag indicating whether or not monitor is
116 * expected to be inflated.
117 * @throws RuntimeException if the {@code monitor} in a wrong state.
118 */
119 public static void verifyMonitorState(AbortProvoker provoker,
120 boolean shouldBeInflated) {
121 verifyMonitorState(provoker.monitor, shouldBeInflated);
122 }
123
124 /**
125 * Get instance of specified AbortProvoker, inflate associated monitor
126 * if needed and then invoke forceAbort method in a loop.
127 *
128 * Usage:
129 * AbortProvoker <AbortType name> [<inflate monitor>
130 * [<iterations> [ <delay>]]]
131 *
132 * Default parameters are:
133 * <ul>
134 * <li>inflate monitor = <b>true</b></li>
135 * <li>iterations = {@code AbortProvoker.DEFAULT_ITERATIONS}</li>
136 * <li>delay = <b>0</b></li>
137 * </ul>
138 */
139 public static void main(String args[]) throws Throwable {
140 Asserts.assertGT(args.length, 0, "At least one argument is required.");
141
142 AbortType abortType = AbortType.lookup(Integer.valueOf(args[0]));
145
146 if (args.length > 1) {
147 monitorShouldBeInflated = Boolean.valueOf(args[1]);
148
149 if (args.length > 2) {
150 iterations = Long.valueOf(args[2]);
151
152 if (args.length > 3) {
153 Thread.sleep(Integer.valueOf(args[3]));
154 }
155 }
156 }
157
158 AbortProvoker provoker = abortType.provoker();
159
160 if (monitorShouldBeInflated) {
161 provoker.inflateMonitor();
162 }
163
164 for (long i = 0; i < iterations; i++) {
165 AbortProvoker.verifyMonitorState(provoker, monitorShouldBeInflated);
166 provoker.forceAbort();
167 }
168 }
169
170 protected final Object monitor;
171
172 protected AbortProvoker() {
173 this(new Object());
174 }
175
176 protected AbortProvoker(Object monitor) {
177 this.monitor = Objects.requireNonNull(monitor);
178 }
179
180 /**
181 * Inflates monitor used by this AbortProvoker instance.
182 * @throws Exception
183 */
184 public void inflateMonitor() throws Exception {
185 AbortProvoker.inflateMonitor(monitor);
|