From c5285b33048808a725498556f3f5a366588f4b80 Mon Sep 17 00:00:00 2001 From: Ben Cheng Date: Sun, 14 Feb 2010 16:17:36 -0800 Subject: [PATCH] Detect system-wide safe mode and configure the VM accordingly. Use pthread_cond_wait instead of timed wait for the system_server process to wait on the go-ahead JIT signal. If the phone is booted under system-wide safe mode, such signal will never come so all VM instances (including the system server) will run in the interpreter-only mode. Bug: 2267590 --- .../src/main/java/dalvik/system/VMRuntime.java | 7 ++++ .../dalvik/src/main/java/dalvik/system/Zygote.java | 8 +++++ vm/Globals.h | 6 ++++ vm/compiler/Compiler.c | 40 ++++++++++++++++++---- vm/native/dalvik_system_VMRuntime.c | 24 ++++++++++++- 5 files changed, 78 insertions(+), 7 deletions(-) diff --git a/libcore/dalvik/src/main/java/dalvik/system/VMRuntime.java b/libcore/dalvik/src/main/java/dalvik/system/VMRuntime.java index 398e7fc4b..e05e4898f 100644 --- a/libcore/dalvik/src/main/java/dalvik/system/VMRuntime.java +++ b/libcore/dalvik/src/main/java/dalvik/system/VMRuntime.java @@ -195,4 +195,11 @@ public final class VMRuntime { */ public native void startJitCompilation(); + /** + * Tells the VM to disable the JIT compiler. If the VM does not have a JIT + * implementation, calling this method should have no effect. + * + * {@hide} + */ + public native void disableJitCompilation(); } diff --git a/libcore/dalvik/src/main/java/dalvik/system/Zygote.java b/libcore/dalvik/src/main/java/dalvik/system/Zygote.java index 4f83d2854..641e85616 100644 --- a/libcore/dalvik/src/main/java/dalvik/system/Zygote.java +++ b/libcore/dalvik/src/main/java/dalvik/system/Zygote.java @@ -38,6 +38,14 @@ public class Zygote { /** disable the JIT compiler */ public static final int DEBUG_ENABLE_SAFEMODE = 1 << 3; + /** + * When set by the system server, all subsequent apps will be launched in + * VM safe mode. + * + * @hide + */ + public static boolean systemInSafeMode = false; + private Zygote() {} /** diff --git a/vm/Globals.h b/vm/Globals.h index 81bcefca5..ddcd2db67 100644 --- a/vm/Globals.h +++ b/vm/Globals.h @@ -794,6 +794,12 @@ struct DvmJitGlobals { /* Framework or stand-alone? */ bool runningInAndroidFramework; + /* Framework callback happened? */ + bool alreadyEnabledViaFramework; + + /* Framework requests to disable the JIT for good */ + bool disableJit; + /* Place arrays at the end to ease the display in gdb sessions */ /* Work order queue for compilations */ diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c index 484f9a392..829713144 100644 --- a/vm/compiler/Compiler.c +++ b/vm/compiler/Compiler.c @@ -397,13 +397,41 @@ static void *compilerThreadStart(void *arg) * up code isn't worth compiling. We'll resume when the framework * signals us that the first screen draw has happened, or the timer * below expires (to catch daemons). + * + * There is a theoretical race between the callback to + * VMRuntime.startJitCompiation and when the compiler thread reaches this + * point. In case the callback happens earlier, in order not to permanently + * hold the system_server (which is not using the timed wait) in + * interpreter-only mode we bypass the delay here. */ - if (gDvmJit.runningInAndroidFramework) { - dvmLockMutex(&gDvmJit.compilerLock); - // TUNING: experiment with the delay & perhaps make it target-specific - dvmRelativeCondWait(&gDvmJit.compilerQueueActivity, - &gDvmJit.compilerLock, 3000, 0); - dvmUnlockMutex(&gDvmJit.compilerLock); + if (gDvmJit.runningInAndroidFramework && + !gDvmJit.alreadyEnabledViaFramework) { + /* + * If the current VM instance is the system server (detected by having + * 0 in gDvm.systemServerPid), we will use the indefinite wait on the + * conditional variable to determine whether to start the JIT or not. + * If the system server detects that the whole system is booted in + * safe mode, the conditional variable will never be signaled and the + * system server will remain in the interpreter-only mode. All + * subsequent apps will be started with the --enable-safemode flag + * explicitly appended. + */ + if (gDvm.systemServerPid == 0) { + dvmLockMutex(&gDvmJit.compilerLock); + pthread_cond_wait(&gDvmJit.compilerQueueActivity, + &gDvmJit.compilerLock); + dvmUnlockMutex(&gDvmJit.compilerLock); + LOGD("JIT started for system_server"); + } else { + dvmLockMutex(&gDvmJit.compilerLock); + /* + * TUNING: experiment with the delay & perhaps make it + * target-specific + */ + dvmRelativeCondWait(&gDvmJit.compilerQueueActivity, + &gDvmJit.compilerLock, 3000, 0); + dvmUnlockMutex(&gDvmJit.compilerLock); + } if (gDvmJit.haltCompilerThread) { return NULL; } diff --git a/vm/native/dalvik_system_VMRuntime.c b/vm/native/dalvik_system_VMRuntime.c index 5a2212038..c020f8ae4 100644 --- a/vm/native/dalvik_system_VMRuntime.c +++ b/vm/native/dalvik_system_VMRuntime.c @@ -188,8 +188,10 @@ static void Dalvik_dalvik_system_VMRuntime_startJitCompilation(const u4* args, JValue* pResult) { #if defined(WITH_JIT) - if (gDvm.executionMode == kExecutionModeJit) { + if (gDvm.executionMode == kExecutionModeJit && + gDvmJit.disableJit == false) { dvmLockMutex(&gDvmJit.compilerLock); + gDvmJit.alreadyEnabledViaFramework = true; pthread_cond_signal(&gDvmJit.compilerQueueActivity); dvmUnlockMutex(&gDvmJit.compilerLock); } @@ -197,6 +199,24 @@ static void Dalvik_dalvik_system_VMRuntime_startJitCompilation(const u4* args, RETURN_VOID(); } +/* + * public native void disableJitCompilation() + * + * Callback function from the framework to indicate that a VM instance wants to + * permanently disable the JIT compiler. Currently only the system server uses + * this interface when it detects system-wide safe mode is enabled. + */ +static void Dalvik_dalvik_system_VMRuntime_disableJitCompilation(const u4* args, + JValue* pResult) +{ +#if defined(WITH_JIT) + if (gDvm.executionMode == kExecutionModeJit) { + gDvmJit.disableJit = true; + } +#endif + RETURN_VOID(); +} + const DalvikNativeMethod dvm_dalvik_system_VMRuntime[] = { { "getTargetHeapUtilization", "()F", Dalvik_dalvik_system_VMRuntime_getTargetHeapUtilization }, @@ -216,5 +236,7 @@ const DalvikNativeMethod dvm_dalvik_system_VMRuntime[] = { Dalvik_dalvik_system_VMRuntime_getExternalBytesAllocated }, { "startJitCompilation", "()V", Dalvik_dalvik_system_VMRuntime_startJitCompilation }, + { "disableJitCompilation", "()V", + Dalvik_dalvik_system_VMRuntime_disableJitCompilation }, { NULL, NULL, NULL }, }; -- 2.11.0