Merge "Use nanoTime() in finalizer watchdog"
diff --git a/libart/src/main/java/java/lang/Daemons.java b/libart/src/main/java/java/lang/Daemons.java
index 568614f..6e05cea 100644
--- a/libart/src/main/java/java/lang/Daemons.java
+++ b/libart/src/main/java/java/lang/Daemons.java
@@ -310,7 +310,7 @@
private boolean needToWork = true; // Only accessed in synchronized methods.
- private long finalizerTimeoutMs = 0; // Lazily initialized.
+ private long finalizerTimeoutNs = 0; // Lazily initialized.
FinalizerWatchdogDaemon() {
super("FinalizerWatchdogDaemon");
@@ -370,17 +370,22 @@
}
/**
- * Sleep for the given number of milliseconds.
+ * Sleep for the given number of nanoseconds, or slightly longer.
* @return false if we were interrupted.
*/
- private boolean sleepForMillis(long durationMillis) {
- long startMillis = System.currentTimeMillis();
+ private boolean sleepForNanos(long durationNanos) {
+ // It's important to base this on nanoTime(), not currentTimeMillis(), since
+ // the former stops counting when the processor isn't running.
+ long startNanos = System.nanoTime();
while (true) {
- long elapsedMillis = System.currentTimeMillis() - startMillis;
- long sleepMillis = durationMillis - elapsedMillis;
- if (sleepMillis <= 0) {
+ long elapsedNanos = System.nanoTime() - startNanos;
+ long sleepNanos = durationNanos - elapsedNanos;
+ if (sleepNanos <= 0) {
return true;
}
+ // Ensure the nano time is always rounded up to the next whole millisecond,
+ // ensuring the delay is >= the requested delay.
+ long sleepMillis = (sleepNanos + NANOS_PER_MILLI - 1) / NANOS_PER_MILLI;
try {
Thread.sleep(sleepMillis);
} catch (InterruptedException e) {
@@ -403,14 +408,15 @@
* null. Only called from a single thread.
*/
private Object waitForFinalization() {
- if (finalizerTimeoutMs == 0) {
- finalizerTimeoutMs = VMRuntime.getRuntime().getFinalizerTimeoutMs();
+ if (finalizerTimeoutNs == 0) {
+ finalizerTimeoutNs =
+ NANOS_PER_MILLI * VMRuntime.getRuntime().getFinalizerTimeoutMs();
// Temporary app backward compatibility. Remove eventually.
- MAX_FINALIZE_NANOS = NANOS_PER_MILLI * finalizerTimeoutMs;
+ MAX_FINALIZE_NANOS = finalizerTimeoutNs;
}
long startCount = FinalizerDaemon.INSTANCE.progressCounter.get();
// Avoid remembering object being finalized, so as not to keep it alive.
- if (!sleepForMillis(finalizerTimeoutMs)) {
+ if (!sleepForNanos(finalizerTimeoutNs)) {
// Don't report possibly spurious timeout if we are interrupted.
return null;
}
@@ -431,7 +437,7 @@
// just finished as we were timing out, in which case we may get null or a later
// one. In this last case, we are very likely to discard it below.
Object finalizing = FinalizerDaemon.INSTANCE.finalizingObject;
- sleepForMillis(500);
+ sleepForNanos(500 * NANOS_PER_MILLI);
// Recheck to make it even less likely we report the wrong finalizing object in
// the case which a very slow finalization just finished as we were timing out.
if (getNeedToWork()