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