blob: b67469029233717c55ac79bd9c4efa21722eb474 [file] [log] [blame]
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import sun.misc.Unsafe;
import java.lang.reflect.Field;
public class Main {
private static Unsafe UNSAFE;
public static void main(String[] args) throws Exception {
setUp();
ParkTester test = new ParkTester();
System.out.println("Test starting");
test.start();
UNSAFE.unpark(test);
clearStack(10);
System.out.println("GC'ing");
System.gc();
System.runFinalization();
System.gc();
System.out.println("Asking thread to park");
test.parkNow = true;
try {
// Give some time to the ParkTester thread to honor the park command.
Thread.sleep(3000);
} catch (InterruptedException ex) {
System.out.println("Main thread interrupted!");
System.exit(1);
}
if (test.success) {
System.out.println("Test succeeded!");
} else {
System.out.println("Test failed.");
}
}
/**
* Set up {@link #UNSAFE}.
*/
public static void setUp() throws Exception{
/*
* Subvert the access check to get the unique Unsafe instance.
* We can do this because there's no security manager
* installed when running the test.
*/
Field field = null;
try {
field = Unsafe.class.getDeclaredField("THE_ONE");
} catch (NoSuchFieldException e1) {
try {
field = Unsafe.class.getDeclaredField("theUnsafe");
} catch (NoSuchFieldException e2) {
throw new RuntimeException("Failed to find THE_ONE or theUnsafe");
}
}
field.setAccessible(true);
UNSAFE = (Unsafe) field.get(null);
}
/**
* Scribbles on the stack to help ensure we don't have a fake
* pointer that would keep would-be garbage alive.
*/
private static void clearStack(int depth) {
int a = 0;
int b = 0;
int c = 0;
int d = 0;
int e = 0;
int f = 0;
int g = 0;
int h = 0;
int i = 0;
int j = 0;
if (depth > 0) {
clearStack(depth - 1);
}
}
private static class ParkTester extends Thread {
public volatile boolean parkNow = false;
public volatile boolean success = false;
public void run() {
while (!parkNow) {
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
// Ignore it.
}
}
long start = System.currentTimeMillis();
UNSAFE.park(false, 500 * 1000000); // 500 msec
long elapsed = System.currentTimeMillis() - start;
if (elapsed > 200) {
System.out.println("park()ed for " + elapsed + " msec");
success = false;
} else {
System.out.println("park() returned quickly");
success = true;
}
}
}
}