1 /* 2 * Copyright (C) 2011 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 import sun.misc.Unsafe; 18 19 import java.lang.reflect.Field; 20 21 public class Main { 22 private static Unsafe UNSAFE; 23 main(String[] args)24 public static void main(String[] args) throws Exception { 25 setUp(); 26 27 ParkTester test = new ParkTester(); 28 29 System.out.println("Test starting"); 30 31 test.start(); 32 UNSAFE.unpark(test); 33 34 System.out.println("GC'ing"); 35 System.gc(); 36 System.runFinalization(); 37 System.gc(); 38 39 System.out.println("Asking thread to park"); 40 test.parkNow = true; 41 42 try { 43 // Give some time to the ParkTester thread to honor the park command. 44 Thread.sleep(3000); 45 } catch (InterruptedException ex) { 46 System.out.println("Main thread interrupted!"); 47 System.exit(1); 48 } 49 50 if (test.success) { 51 System.out.println("Test succeeded!"); 52 } else { 53 System.out.println("Test failed."); 54 test.printTimes(); 55 System.out.println("Value of success = " + test.success); 56 Thread.sleep(3000); 57 System.out.println("Value of success after sleeping = " + test.success); 58 test.printTimes(); // In case they weren't ready the first time. 59 } 60 } 61 62 /** 63 * Set up {@link #UNSAFE}. 64 */ setUp()65 public static void setUp() throws Exception{ 66 /* 67 * Subvert the access check to get the unique Unsafe instance. 68 * We can do this because there's no security manager 69 * installed when running the test. 70 */ 71 Field field = null; 72 try { 73 field = Unsafe.class.getDeclaredField("THE_ONE"); 74 } catch (NoSuchFieldException e1) { 75 try { 76 field = Unsafe.class.getDeclaredField("theUnsafe"); 77 } catch (NoSuchFieldException e2) { 78 throw new RuntimeException("Failed to find THE_ONE or theUnsafe"); 79 } 80 } 81 field.setAccessible(true); 82 UNSAFE = (Unsafe) field.get(null); 83 } 84 85 private static class ParkTester extends Thread { 86 public volatile boolean parkNow = false; 87 public volatile boolean success = false; 88 public volatile long startTime = 0; 89 public volatile long elapsedTime = 0; 90 public volatile long finishTime = 0; 91 run()92 public void run() { 93 while (!parkNow) { 94 try { 95 Thread.sleep(500); 96 } catch (InterruptedException ex) { 97 // Ignore it. 98 } 99 } 100 101 long start = System.currentTimeMillis(); 102 UNSAFE.park(false, 500 * 1000000); // 500 msec 103 long elapsed = System.currentTimeMillis() - start; 104 105 if (elapsed > 200) { 106 success = false; 107 System.out.println("park()ed for " + elapsed + " msec"); 108 } else { 109 success = true; 110 // println is occasionally very slow. 111 // But output still appears before main thread output. 112 System.out.println("park() returned quickly"); 113 finishTime = System.currentTimeMillis(); 114 startTime = start; 115 elapsedTime = elapsed; 116 } 117 } 118 printTimes()119 public void printTimes() { 120 System.out.println("Started at " + startTime + "ms, took " + elapsedTime 121 + "ms, signalled at " + finishTime + "ms"); 122 } 123 } 124 } 125