summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Light <allight@google.com>2019-02-11 23:13:53 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2019-02-11 23:13:53 +0000
commitcbda2926f997a596c7aa7cbba944c836d0bc099f (patch)
treef7d4aef83ea5b398be39813a74cf6e7c2c1d8818
parent233de2b7107880b2d3774d70941bde4c842769e5 (diff)
parent89b46205a8be6a2cf6264c066290ed29ef8a2d61 (diff)
Merge "Mark threads started by Daemons.java as systemDaemon"
-rw-r--r--libart/src/main/java/java/lang/Daemons.java47
-rw-r--r--ojluni/src/main/java/java/lang/Thread.java42
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.