From a57efa2083afd417b0850a0e2a904780c90e1e1d Mon Sep 17 00:00:00 2001 From: Mathieu Chartier Date: Mon, 15 Dec 2014 14:24:56 -0800 Subject: 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 --- libart/src/main/java/dalvik/system/VMRuntime.java | 2 ++ libart/src/main/java/java/lang/Daemons.java | 32 ++++++++--------------- 2 files changed, 13 insertions(+), 21 deletions(-) (limited to 'libart/src/main/java') 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) { } } } -- cgit v1.1