summaryrefslogtreecommitdiffstats
path: root/libart
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2014-12-15 14:24:56 -0800
committerMathieu Chartier <mathieuc@google.com>2014-12-15 15:19:37 -0800
commita57efa2083afd417b0850a0e2a904780c90e1e1d (patch)
tree85d639a2d35abb97421771cbe869a8f433720202 /libart
parent35f07bdfc3b99587387e02846a716bf06fe614d9 (diff)
downloadlibcore-a57efa2083afd417b0850a0e2a904780c90e1e1d.zip
libcore-a57efa2083afd417b0850a0e2a904780c90e1e1d.tar.gz
libcore-a57efa2083afd417b0850a0e2a904780c90e1e1d.tar.bz2
Move GC daemon locking logic into heap
Fixes deadlock caused by acquirng the mutator lock while synchronizing on the daemon thread. Bug: 18739541 Change-Id: Ib3ac3788081d3d471195a6e3a8ed163237616a4f
Diffstat (limited to 'libart')
-rw-r--r--libart/src/main/java/dalvik/system/VMRuntime.java2
-rw-r--r--libart/src/main/java/java/lang/Daemons.java32
2 files changed, 13 insertions, 21 deletions
diff --git a/libart/src/main/java/dalvik/system/VMRuntime.java b/libart/src/main/java/dalvik/system/VMRuntime.java
index f778af0..58094d8 100644
--- a/libart/src/main/java/dalvik/system/VMRuntime.java
+++ b/libart/src/main/java/dalvik/system/VMRuntime.java
@@ -297,6 +297,8 @@ public final class VMRuntime {
public native void trimHeap();
public native void concurrentGC();
+ public native void requestConcurrentGC();
+ public native void waitForConcurrentGCRequest();
/**
* Let the heap know of the new process state. This can change allocation and garbage collection
diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java
index 726f782..d3f62c2 100644
--- a/libart/src/main/java/java/lang/Daemons.java
+++ b/libart/src/main/java/java/lang/Daemons.java
@@ -80,6 +80,10 @@ public final class Daemons {
}
public synchronized void interrupt() {
+ interrupt(thread);
+ }
+
+ public synchronized void interrupt(Thread thread) {
if (thread == null) {
throw new IllegalStateException("not running");
}
@@ -99,7 +103,7 @@ public final class Daemons {
if (threadToStop == null) {
throw new IllegalStateException("not running");
}
- threadToStop.interrupt();
+ interrupt(threadToStop);
while (true) {
try {
threadToStop.join();
@@ -311,34 +315,20 @@ public final class Daemons {
}
}
- // Invoked by the GC to request that the HeapTrimmerDaemon thread attempt to trim the heap.
- public static void requestGC() {
- GCDaemon.INSTANCE.requestGC();
- }
-
private static class GCDaemon extends Daemon {
private static final GCDaemon INSTANCE = new GCDaemon();
- private static final AtomicBoolean atomicBoolean = new AtomicBoolean();
- public void requestGC() {
- if (atomicBoolean.getAndSet(true)) {
- return;
- }
- synchronized (this) {
- notify();
- }
- atomicBoolean.set(false);
+ // Overrides the Daemon.interupt method which is called from Daemons.stop.
+ public void interrupt(Thread thread) {
+ // Notifies the daemon thread.
+ VMRuntime.getRuntime().requestConcurrentGC();
}
@Override public void run() {
while (isRunning()) {
- try {
- synchronized (this) {
- // Wait until a request comes in.
- wait();
- }
+ VMRuntime.getRuntime().waitForConcurrentGCRequest();
+ if (isRunning()) {
VMRuntime.getRuntime().concurrentGC();
- } catch (InterruptedException ignored) {
}
}
}