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