Add -XX:ForceJavaZygoteForkLoop flag

Setting this to true effectively disables the zygote native fork
loop, either for testing/measurement purposes, or as a fallback.

Bug: 192020504
Test: Check logcat with and without the flag.
Change-Id: I83c401d21ae2797442011d9ac6f23c78990920bd
Merged-In: I83c401d21ae2797442011d9ac6f23c78990920bd
(cherry picked from commit 1792c6ff1c9838dfbe948be124dc1a8501fc6636)
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 2c18ddb..050233d 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -442,11 +442,17 @@
   Runtime::Current()->SetZygoteNoThreadSection(false);
 }
 
-static jboolean ZygoteHooks_nativeZygoteJitEnabled(JNIEnv* env ATTRIBUTE_UNUSED,
-                                                   jclass klass ATTRIBUTE_UNUSED) {
+static jboolean ZygoteHooks_nativeZygoteLongSuspendOk(JNIEnv* env ATTRIBUTE_UNUSED,
+                                                    jclass klass ATTRIBUTE_UNUSED) {
+  // Indefinite thread suspensions are not OK if we're supposed to be JIT-compiling for other
+  // processes.  We only care about JIT compilation that affects other processes.  The zygote
+  // itself doesn't run appreciable amounts of Java code when running single-threaded, so
+  // suspending the JIT in non-jit-zygote mode is OK.
+  // TODO: Make this potentially return true once we're done with JIT compilation in JIT Zygote.
   // Only called in zygote. Thus static is OK here.
-  static bool result = jit::Jit::InZygoteUsingJit();
-  return result ? JNI_TRUE : JNI_FALSE;
+  static bool isJitZygote = jit::Jit::InZygoteUsingJit();
+  static bool explicitlyDisabled = Runtime::Current()->IsJavaZygoteForkLoopRequired();
+  return (isJitZygote || explicitlyDisabled) ? JNI_FALSE : JNI_TRUE;
 }
 
 
@@ -455,7 +461,7 @@
   NATIVE_METHOD(ZygoteHooks, nativePostZygoteFork, "()V"),
   NATIVE_METHOD(ZygoteHooks, nativePostForkSystemServer, "(I)V"),
   NATIVE_METHOD(ZygoteHooks, nativePostForkChild, "(JIZZLjava/lang/String;)V"),
-  NATIVE_METHOD(ZygoteHooks, nativeZygoteJitEnabled, "()Z"),
+  NATIVE_METHOD(ZygoteHooks, nativeZygoteLongSuspendOk, "()Z"),
   NATIVE_METHOD(ZygoteHooks, startZygoteNoThreadCreation, "()V"),
   NATIVE_METHOD(ZygoteHooks, stopZygoteNoThreadCreation, "()V"),
 };
diff --git a/runtime/parsed_options.cc b/runtime/parsed_options.cc
index 8ce9144..3e1fd4f 100644
--- a/runtime/parsed_options.cc
+++ b/runtime/parsed_options.cc
@@ -441,6 +441,10 @@
           .WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
           .IntoKey(M::VerifierMissingKThrowFatal)
+      .Define("-XX:ForceJavaZygoteForkLoop=_")
+          .WithType<bool>()
+          .WithValueMap({{"false", false}, {"true", true}})
+          .IntoKey(M::ForceJavaZygoteForkLoop)
       .Define("-XX:PerfettoHprof=_")
           .WithType<bool>()
           .WithValueMap({{"false", false}, {"true", true}})
diff --git a/runtime/runtime.cc b/runtime/runtime.cc
index 1e563dd..669c613 100644
--- a/runtime/runtime.cc
+++ b/runtime/runtime.cc
@@ -1348,6 +1348,7 @@
   MemMap::Init();
 
   verifier_missing_kthrow_fatal_ = runtime_options.GetOrDefault(Opt::VerifierMissingKThrowFatal);
+  force_java_zygote_fork_loop_ = runtime_options.GetOrDefault(Opt::ForceJavaZygoteForkLoop);
   perfetto_hprof_enabled_ = runtime_options.GetOrDefault(Opt::PerfettoHprof);
   perfetto_javaheapprof_enabled_ = runtime_options.GetOrDefault(Opt::PerfettoJavaHeapStackProf);
 
diff --git a/runtime/runtime.h b/runtime/runtime.h
index 1486a9a..68456cd 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -991,6 +991,10 @@
     return verifier_missing_kthrow_fatal_;
   }
 
+  bool IsJavaZygoteForkLoopRequired() const {
+    return force_java_zygote_fork_loop_;
+  }
+
   bool IsPerfettoHprofEnabled() const {
     return perfetto_hprof_enabled_;
   }
@@ -1413,6 +1417,7 @@
   std::atomic<bool> startup_completed_ = false;
 
   bool verifier_missing_kthrow_fatal_;
+  bool force_java_zygote_fork_loop_;
   bool perfetto_hprof_enabled_;
   bool perfetto_javaheapprof_enabled_;
 
diff --git a/runtime/runtime_options.def b/runtime/runtime_options.def
index 966bc83..ddbbfec 100644
--- a/runtime/runtime_options.def
+++ b/runtime/runtime_options.def
@@ -176,6 +176,10 @@
 RUNTIME_OPTIONS_KEY (bool,                FastClassNotFoundException,     true)
 RUNTIME_OPTIONS_KEY (bool,                VerifierMissingKThrowFatal,     true)
 
+// Setting this to true causes ART to disable Zygote native fork loop. ART also
+// internally enables this if ZygoteJit is enabled.
+RUNTIME_OPTIONS_KEY (bool,                ForceJavaZygoteForkLoop,        false)
+
 // Whether to allow loading of the perfetto hprof plugin.
 // Even with this option set, we will still only actually load the plugin
 // if we are on a userdebug build or the app is debuggable or profileable.