diff options
-rw-r--r-- | libart/src/main/java/java/lang/Daemons.java | 47 | ||||
-rw-r--r-- | ojluni/src/main/java/java/lang/Thread.java | 42 |
2 files changed, 76 insertions, 13 deletions
diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java index a04bee8267..c8275327a1 100644 --- a/libart/src/main/java/java/lang/Daemons.java +++ b/libart/src/main/java/java/lang/Daemons.java @@ -25,6 +25,7 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeoutException; import libcore.util.EmptyArray; @@ -40,28 +41,44 @@ public final class Daemons { private static final int NANOS_PER_SECOND = NANOS_PER_MILLI * 1000; @UnsupportedAppUsage private static final long MAX_FINALIZE_NANOS = 10L * NANOS_PER_SECOND; + private static final Daemon[] DAEMONS = new Daemon[] { + HeapTaskDaemon.INSTANCE, + ReferenceQueueDaemon.INSTANCE, + FinalizerDaemon.INSTANCE, + FinalizerWatchdogDaemon.INSTANCE, + }; + private static final CountDownLatch POST_ZYGOTE_START_LATCH = new CountDownLatch(DAEMONS.length); + private static final CountDownLatch PRE_ZYGOTE_START_LATCH = new CountDownLatch(DAEMONS.length); + + private static boolean postZygoteFork = false; @UnsupportedAppUsage public static void start() { - ReferenceQueueDaemon.INSTANCE.start(); - FinalizerDaemon.INSTANCE.start(); - FinalizerWatchdogDaemon.INSTANCE.start(); - HeapTaskDaemon.INSTANCE.start(); + for (Daemon daemon : DAEMONS) { + daemon.start(); + } } public static void startPostZygoteFork() { - ReferenceQueueDaemon.INSTANCE.startPostZygoteFork(); - FinalizerDaemon.INSTANCE.startPostZygoteFork(); - FinalizerWatchdogDaemon.INSTANCE.startPostZygoteFork(); - HeapTaskDaemon.INSTANCE.startPostZygoteFork(); + postZygoteFork = true; + for (Daemon daemon : DAEMONS) { + daemon.startPostZygoteFork(); + } } @UnsupportedAppUsage public static void stop() { - HeapTaskDaemon.INSTANCE.stop(); - ReferenceQueueDaemon.INSTANCE.stop(); - FinalizerDaemon.INSTANCE.stop(); - FinalizerWatchdogDaemon.INSTANCE.stop(); + for (Daemon daemon : DAEMONS) { + daemon.stop(); + } + } + + private static void waitForDaemonStart() throws Exception { + if (postZygoteFork) { + POST_ZYGOTE_START_LATCH.await(); + } else { + PRE_ZYGOTE_START_LATCH.await(); + } } /** @@ -95,16 +112,20 @@ public final class Daemons { } thread = new Thread(ThreadGroup.systemThreadGroup, this, name); thread.setDaemon(true); + thread.setSystemDaemon(true); thread.start(); } - public void run() { + public final void run() { if (postZygoteFork) { // We don't set the priority before the Thread.start() call above because // Thread.start() will call SetNativePriority and overwrite the desired native // priority. We (may) use a native priority that doesn't have a corresponding // java.lang.Thread-level priority (native priorities are more coarse-grained.) VMRuntime.getRuntime().setSystemDaemonThreadPriority(); + POST_ZYGOTE_START_LATCH.countDown(); + } else { + PRE_ZYGOTE_START_LATCH.countDown(); } runInternal(); } diff --git a/ojluni/src/main/java/java/lang/Thread.java b/ojluni/src/main/java/java/lang/Thread.java index 591d14af48..0ca90743ae 100644 --- a/ojluni/src/main/java/java/lang/Thread.java +++ b/ojluni/src/main/java/java/lang/Thread.java @@ -236,6 +236,11 @@ class Thread implements Runnable { /* For generating thread ID */ private static long threadSeqNumber; + + // Android-added: The concept of "system-daemon" threads. See java.lang.Daemons. + /** True if this thread is managed by {@link Daemons}. */ + private boolean systemDaemon = false; + /* Java thread status for tools, * initialized to indicate thread 'not yet started' */ @@ -2182,6 +2187,43 @@ class Thread implements Runnable { getUncaughtExceptionHandler().uncaughtException(this, e); } + // BEGIN Android-added: The concept of "system-daemon" threads. See java.lang.Daemons. + /** + * Marks this thread as either a special runtime-managed ("system daemon") + * thread or a normal (i.e. app code created) daemon thread.) + * + * <p>System daemon threads get special handling when starting up in some + * cases. + * + * <p>This method must be invoked before the thread is started. + * + * <p>This method must only be invoked on Thread instances that have already + * had {@code setDaemon(true)} called on them. + * + * <p>Package-private since only {@link java.lang.Daemons} needs to call + * this. + * + * @param on if {@code true}, marks this thread as a system daemon thread + * + * @throws IllegalThreadStateException + * if this thread is {@linkplain #isAlive alive} or not a + * {@linkplain #isDaemon daemon} + * + * @throws SecurityException + * if {@link #checkAccess} determines that the current + * thread cannot modify this thread + * + * @hide For use by Daemons.java only. + */ + final void setSystemDaemon(boolean on) { + checkAccess(); + if (isAlive() || !isDaemon()) { + throw new IllegalThreadStateException(); + } + systemDaemon = on; + } + // END Android-added: The concept of "system-daemon" threads. See java.lang.Daemons. + /** * Removes from the specified map any keys that have been enqueued * on the specified reference queue. |