diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-12-15 14:24:56 -0800 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-12-15 15:19:37 -0800 |
commit | a57efa2083afd417b0850a0e2a904780c90e1e1d (patch) | |
tree | 85d639a2d35abb97421771cbe869a8f433720202 /libart | |
parent | 35f07bdfc3b99587387e02846a716bf06fe614d9 (diff) | |
download | libcore-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.java | 2 | ||||
-rw-r--r-- | libart/src/main/java/java/lang/Daemons.java | 32 |
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) { } } } |