ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/LockSupportTest.java
Revision: 1.26
Committed: Mon Oct 12 20:12:50 2015 UTC (8 years, 7 months ago) by jsr166
Branch: MAIN
Changes since 1.25: +6 -0 lines
Log Message:
guard against lost unpark via JDK-8074773

File Contents

# Content
1 /*
2 * Written by Doug Lea and Martin Buchholz with assistance from
3 * members of JCP JSR-166 Expert Group and released to the public
4 * domain, as explained at
5 * http://creativecommons.org/publicdomain/zero/1.0/
6 * Other contributors include Andrew Wright, Jeffrey Hayes,
7 * Pat Fisher, Mike Judd.
8 */
9
10 import static java.util.concurrent.TimeUnit.MILLISECONDS;
11
12 import java.util.concurrent.CountDownLatch;
13 import java.util.concurrent.atomic.AtomicBoolean;
14 import java.util.concurrent.locks.LockSupport;
15
16 import junit.framework.Test;
17 import junit.framework.TestSuite;
18
19 public class LockSupportTest extends JSR166TestCase {
20 public static void main(String[] args) {
21 main(suite(), args);
22 }
23
24 public static Test suite() {
25 return new TestSuite(LockSupportTest.class);
26 }
27
28 static {
29 // Reduce the risk of rare disastrous classloading in first call to
30 // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
31 Class<?> ensureLoaded = LockSupport.class;
32 }
33
34 /**
35 * Returns the blocker object used by tests in this file.
36 * Any old object will do; we'll return a convenient one.
37 */
38 static Object theBlocker() {
39 return LockSupportTest.class;
40 }
41
42 enum ParkMethod {
43 park() {
44 void park() {
45 LockSupport.park();
46 }
47 void park(long millis) {
48 throw new UnsupportedOperationException();
49 }
50 },
51 parkUntil() {
52 void park(long millis) {
53 LockSupport.parkUntil(deadline(millis));
54 }
55 },
56 parkNanos() {
57 void park(long millis) {
58 LockSupport.parkNanos(MILLISECONDS.toNanos(millis));
59 }
60 },
61 parkBlocker() {
62 void park() {
63 LockSupport.park(theBlocker());
64 }
65 void park(long millis) {
66 throw new UnsupportedOperationException();
67 }
68 },
69 parkUntilBlocker() {
70 void park(long millis) {
71 LockSupport.parkUntil(theBlocker(), deadline(millis));
72 }
73 },
74 parkNanosBlocker() {
75 void park(long millis) {
76 LockSupport.parkNanos(theBlocker(),
77 MILLISECONDS.toNanos(millis));
78 }
79 };
80
81 void park() { park(2 * LONG_DELAY_MS); }
82 abstract void park(long millis);
83
84 /** Returns a deadline to use with parkUntil. */
85 long deadline(long millis) {
86 // beware of rounding
87 return System.currentTimeMillis() + millis + 1;
88 }
89 }
90
91 /**
92 * park is released by subsequent unpark
93 */
94 public void testParkBeforeUnpark_park() {
95 testParkBeforeUnpark(ParkMethod.park);
96 }
97 public void testParkBeforeUnpark_parkNanos() {
98 testParkBeforeUnpark(ParkMethod.parkNanos);
99 }
100 public void testParkBeforeUnpark_parkUntil() {
101 testParkBeforeUnpark(ParkMethod.parkUntil);
102 }
103 public void testParkBeforeUnpark_parkBlocker() {
104 testParkBeforeUnpark(ParkMethod.parkBlocker);
105 }
106 public void testParkBeforeUnpark_parkNanosBlocker() {
107 testParkBeforeUnpark(ParkMethod.parkNanosBlocker);
108 }
109 public void testParkBeforeUnpark_parkUntilBlocker() {
110 testParkBeforeUnpark(ParkMethod.parkUntilBlocker);
111 }
112 public void testParkBeforeUnpark(final ParkMethod parkMethod) {
113 final CountDownLatch pleaseUnpark = new CountDownLatch(1);
114 Thread t = newStartedThread(new CheckedRunnable() {
115 public void realRun() {
116 pleaseUnpark.countDown();
117 parkMethod.park();
118 }});
119
120 await(pleaseUnpark);
121 LockSupport.unpark(t);
122 awaitTermination(t);
123 }
124
125 /**
126 * park is released by preceding unpark
127 */
128 public void testParkAfterUnpark_park() {
129 testParkAfterUnpark(ParkMethod.park);
130 }
131 public void testParkAfterUnpark_parkNanos() {
132 testParkAfterUnpark(ParkMethod.parkNanos);
133 }
134 public void testParkAfterUnpark_parkUntil() {
135 testParkAfterUnpark(ParkMethod.parkUntil);
136 }
137 public void testParkAfterUnpark_parkBlocker() {
138 testParkAfterUnpark(ParkMethod.parkBlocker);
139 }
140 public void testParkAfterUnpark_parkNanosBlocker() {
141 testParkAfterUnpark(ParkMethod.parkNanosBlocker);
142 }
143 public void testParkAfterUnpark_parkUntilBlocker() {
144 testParkAfterUnpark(ParkMethod.parkUntilBlocker);
145 }
146 public void testParkAfterUnpark(final ParkMethod parkMethod) {
147 final CountDownLatch pleaseUnpark = new CountDownLatch(1);
148 final AtomicBoolean pleasePark = new AtomicBoolean(false);
149 Thread t = newStartedThread(new CheckedRunnable() {
150 public void realRun() {
151 pleaseUnpark.countDown();
152 while (!pleasePark.get())
153 Thread.yield();
154 parkMethod.park();
155 }});
156
157 await(pleaseUnpark);
158 LockSupport.unpark(t);
159 pleasePark.set(true);
160 awaitTermination(t);
161 }
162
163 /**
164 * park is released by subsequent interrupt
165 */
166 public void testParkBeforeInterrupt_park() {
167 testParkBeforeInterrupt(ParkMethod.park);
168 }
169 public void testParkBeforeInterrupt_parkNanos() {
170 testParkBeforeInterrupt(ParkMethod.parkNanos);
171 }
172 public void testParkBeforeInterrupt_parkUntil() {
173 testParkBeforeInterrupt(ParkMethod.parkUntil);
174 }
175 public void testParkBeforeInterrupt_parkBlocker() {
176 testParkBeforeInterrupt(ParkMethod.parkBlocker);
177 }
178 public void testParkBeforeInterrupt_parkNanosBlocker() {
179 testParkBeforeInterrupt(ParkMethod.parkNanosBlocker);
180 }
181 public void testParkBeforeInterrupt_parkUntilBlocker() {
182 testParkBeforeInterrupt(ParkMethod.parkUntilBlocker);
183 }
184 public void testParkBeforeInterrupt(final ParkMethod parkMethod) {
185 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
186 Thread t = newStartedThread(new CheckedRunnable() {
187 public void realRun() {
188 pleaseInterrupt.countDown();
189 do {
190 parkMethod.park();
191 // park may return spuriously
192 } while (! Thread.currentThread().isInterrupted());
193 }});
194
195 await(pleaseInterrupt);
196 assertThreadStaysAlive(t);
197 t.interrupt();
198 awaitTermination(t);
199 }
200
201 /**
202 * park is released by preceding interrupt
203 */
204 public void testParkAfterInterrupt_park() {
205 testParkAfterInterrupt(ParkMethod.park);
206 }
207 public void testParkAfterInterrupt_parkNanos() {
208 testParkAfterInterrupt(ParkMethod.parkNanos);
209 }
210 public void testParkAfterInterrupt_parkUntil() {
211 testParkAfterInterrupt(ParkMethod.parkUntil);
212 }
213 public void testParkAfterInterrupt_parkBlocker() {
214 testParkAfterInterrupt(ParkMethod.parkBlocker);
215 }
216 public void testParkAfterInterrupt_parkNanosBlocker() {
217 testParkAfterInterrupt(ParkMethod.parkNanosBlocker);
218 }
219 public void testParkAfterInterrupt_parkUntilBlocker() {
220 testParkAfterInterrupt(ParkMethod.parkUntilBlocker);
221 }
222 public void testParkAfterInterrupt(final ParkMethod parkMethod) {
223 final CountDownLatch pleaseInterrupt = new CountDownLatch(1);
224 final AtomicBoolean pleasePark = new AtomicBoolean(false);
225 Thread t = newStartedThread(new CheckedRunnable() {
226 public void realRun() throws Exception {
227 pleaseInterrupt.countDown();
228 while (!pleasePark.get())
229 Thread.yield();
230 assertTrue(Thread.currentThread().isInterrupted());
231 parkMethod.park();
232 assertTrue(Thread.currentThread().isInterrupted());
233 }});
234
235 await(pleaseInterrupt);
236 t.interrupt();
237 pleasePark.set(true);
238 awaitTermination(t);
239 }
240
241 /**
242 * timed park times out if not unparked
243 */
244 public void testParkTimesOut_parkNanos() {
245 testParkTimesOut(ParkMethod.parkNanos);
246 }
247 public void testParkTimesOut_parkUntil() {
248 testParkTimesOut(ParkMethod.parkUntil);
249 }
250 public void testParkTimesOut_parkNanosBlocker() {
251 testParkTimesOut(ParkMethod.parkNanosBlocker);
252 }
253 public void testParkTimesOut_parkUntilBlocker() {
254 testParkTimesOut(ParkMethod.parkUntilBlocker);
255 }
256 public void testParkTimesOut(final ParkMethod parkMethod) {
257 Thread t = newStartedThread(new CheckedRunnable() {
258 public void realRun() {
259 for (;;) {
260 long startTime = System.nanoTime();
261 parkMethod.park(timeoutMillis());
262 // park may return spuriously
263 if (millisElapsedSince(startTime) >= timeoutMillis())
264 return;
265 }
266 }});
267
268 awaitTermination(t);
269 }
270
271 /**
272 * getBlocker(null) throws NullPointerException
273 */
274 public void testGetBlockerNull() {
275 try {
276 LockSupport.getBlocker(null);
277 shouldThrow();
278 } catch (NullPointerException success) {}
279 }
280
281 /**
282 * getBlocker returns the blocker object passed to park
283 */
284 public void testGetBlocker_parkBlocker() {
285 testGetBlocker(ParkMethod.parkBlocker);
286 }
287 public void testGetBlocker_parkNanosBlocker() {
288 testGetBlocker(ParkMethod.parkNanosBlocker);
289 }
290 public void testGetBlocker_parkUntilBlocker() {
291 testGetBlocker(ParkMethod.parkUntilBlocker);
292 }
293 public void testGetBlocker(final ParkMethod parkMethod) {
294 final CountDownLatch started = new CountDownLatch(1);
295 Thread t = newStartedThread(new CheckedRunnable() {
296 public void realRun() {
297 Thread t = Thread.currentThread();
298 started.countDown();
299 do {
300 assertNull(LockSupport.getBlocker(t));
301 parkMethod.park();
302 assertNull(LockSupport.getBlocker(t));
303 // park may return spuriously
304 } while (! Thread.currentThread().isInterrupted());
305 }});
306
307 long startTime = System.nanoTime();
308 await(started);
309 for (;;) {
310 Object x = LockSupport.getBlocker(t);
311 if (x == theBlocker()) { // success
312 t.interrupt();
313 awaitTermination(t);
314 assertNull(LockSupport.getBlocker(t));
315 return;
316 } else {
317 assertNull(x); // ok
318 if (millisElapsedSince(startTime) > LONG_DELAY_MS)
319 fail("timed out");
320 Thread.yield();
321 }
322 }
323 }
324
325 /**
326 * timed park(0) returns immediately.
327 *
328 * Requires hotspot fix for:
329 * 6763959 java.util.concurrent.locks.LockSupport.parkUntil(0) blocks forever
330 * which is in jdk7-b118 and 6u25.
331 */
332 public void testPark0_parkNanos() {
333 testPark0(ParkMethod.parkNanos);
334 }
335 public void testPark0_parkUntil() {
336 testPark0(ParkMethod.parkUntil);
337 }
338 public void testPark0_parkNanosBlocker() {
339 testPark0(ParkMethod.parkNanosBlocker);
340 }
341 public void testPark0_parkUntilBlocker() {
342 testPark0(ParkMethod.parkUntilBlocker);
343 }
344 public void testPark0(final ParkMethod parkMethod) {
345 Thread t = newStartedThread(new CheckedRunnable() {
346 public void realRun() {
347 parkMethod.park(0L);
348 }});
349
350 awaitTermination(t);
351 }
352
353 /**
354 * timed park(Long.MIN_VALUE) returns immediately.
355 */
356 public void testParkNeg_parkNanos() {
357 testParkNeg(ParkMethod.parkNanos);
358 }
359 public void testParkNeg_parkUntil() {
360 testParkNeg(ParkMethod.parkUntil);
361 }
362 public void testParkNeg_parkNanosBlocker() {
363 testParkNeg(ParkMethod.parkNanosBlocker);
364 }
365 public void testParkNeg_parkUntilBlocker() {
366 testParkNeg(ParkMethod.parkUntilBlocker);
367 }
368 public void testParkNeg(final ParkMethod parkMethod) {
369 Thread t = newStartedThread(new CheckedRunnable() {
370 public void realRun() {
371 parkMethod.park(Long.MIN_VALUE);
372 }});
373
374 awaitTermination(t);
375 }
376 }