Bug 771765 - Support template content process, part 8: process initialization flow changes. r=khuey
authorThinker Lee <tlee@mozilla.com>, Cervantes Yu <cyu@mozilla.com>
Mon, 03 Jun 2013 18:14:46 +0800
changeset 163145 b0b107f7e678ad226ca91d43896523f0ed5d71d3
parent 163144 221697fc3a86062a1536d8328a7af54444bd5bf3
child 163146 eb41ace1d0b568b26dea6df503bf8d5cc0c1819f
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs771765
milestone27.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 771765 - Support template content process, part 8: process initialization flow changes. r=khuey Changes initialization code for the template process: * Let the process run for NUWA_PREPARATION_TIME ms and then start freezing the threads. * Delay android binder thread pool creation after the content process is forked from the template and other thread recreation has finished. * Poke the app shell after the content process is forked from the template.
ipc/app/MozillaRuntimeMain.cpp
toolkit/xre/nsEmbedFunctions.cpp
widget/gonk/nsAppShell.cpp
--- a/ipc/app/MozillaRuntimeMain.cpp
+++ b/ipc/app/MozillaRuntimeMain.cpp
@@ -36,35 +36,66 @@
 # define LOGE_IF(cond, ...) \
      ( (CONDITION(cond)) \
      ? ((void)__android_log_print(ANDROID_LOG_ERROR, \
        "Gecko:MozillaRntimeMain", __VA_ARGS__)) \
      : (void)0 )
 
 #endif
 
-int
-main(int argc, char* argv[])
-{
+#ifdef MOZ_NUWA_PROCESS
+#include <binder/ProcessState.h>
+#include "ipc/Nuwa.h"
+#endif
+
 #ifdef MOZ_WIDGET_GONK
-    // This creates a ThreadPool for binder ipc. A ThreadPool is necessary to
-    // receive binder calls, though not necessary to send binder calls.
-    // ProcessState::Self() also needs to be called once on the main thread to
-    // register the main thread with the binder driver.
-
+static void
+InitializeBinder(void *aDummy) {
     // Change thread priority to 0 only during calling ProcessState::self().
     // The priority is registered to binder driver and used for default Binder
     // Thread's priority. 
     // To change the process's priority to small value need's root permission.
     int curPrio = getpriority(PRIO_PROCESS, 0);
     int err = setpriority(PRIO_PROCESS, 0, 0);
     MOZ_ASSERT(!err);
     LOGE_IF(err, "setpriority failed. Current process needs root permission.");
     android::ProcessState::self()->startThreadPool();
     setpriority(PRIO_PROCESS, 0, curPrio);
+}
+#endif
+
+int
+main(int argc, char* argv[])
+{
+#ifdef MOZ_NUWA_PROCESS
+    bool isNuwa = false;
+    for (int i = 1; i < argc; i++) {
+        if (strcmp(argv[i], "-nuwa") == 0) {
+            PrepareNuwaProcess();
+            isNuwa = true;
+            break;
+        }
+    }
+#endif
+
+#ifdef MOZ_WIDGET_GONK
+    // This creates a ThreadPool for binder ipc. A ThreadPool is necessary to
+    // receive binder calls, though not necessary to send binder calls.
+    // ProcessState::Self() also needs to be called once on the main thread to
+    // register the main thread with the binder driver.
+
+#ifdef MOZ_NUWA_PROCESS
+    if (!isNuwa) {
+        InitializeBinder(nullptr);
+    } else {
+        NuwaAddFinalConstructor(&InitializeBinder, nullptr);
+    }
+#else
+    InitializeBinder(nullptr);
+#endif
 #endif
 
 #if defined(XP_WIN) && defined(DEBUG_bent)
     MessageBox(nullptr, L"Hi", L"Hi", MB_OK);
 #endif
 
     // Check for the absolute minimum number of args we need to move
     // forward here. We expect the last arg to be the child process type.
--- a/toolkit/xre/nsEmbedFunctions.cpp
+++ b/toolkit/xre/nsEmbedFunctions.cpp
@@ -72,16 +72,21 @@
 
 #ifdef MOZ_IPDL_TESTS
 #include "mozilla/_ipdltest/IPDLUnitTests.h"
 #include "mozilla/_ipdltest/IPDLUnitTestProcessChild.h"
 
 using mozilla::_ipdltest::IPDLUnitTestProcessChild;
 #endif  // ifdef MOZ_IPDL_TESTS
 
+#ifdef MOZ_NUWA_PROCESS
+#include "nsITimer.h"
+#define NUWA_PREPARATION_TIME 1000
+#endif
+
 using namespace mozilla;
 
 using mozilla::ipc::BrowserProcessSubThread;
 using mozilla::ipc::GeckoChildProcessHost;
 using mozilla::ipc::IOThreadChild;
 using mozilla::ipc::ProcessChild;
 using mozilla::ipc::ScopedXREEmbed;
 
@@ -97,16 +102,23 @@ using mozilla::ipc::XPCShellEnvironment;
 using mozilla::startup::sChildProcessType;
 
 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
 
 #ifdef XP_WIN
 static const PRUnichar kShellLibraryName[] =  L"shell32.dll";
 #endif
 
+#ifdef MOZ_NUWA_PROCESS
+extern "C" {
+void PrepareNuwaProcess() __attribute__((weak));
+void MakeNuwaProcess() __attribute__((weak));
+};
+#endif
+
 nsresult
 XRE_LockProfileDirectory(nsIFile* aDirectory,
                          nsISupports* *aLockObject)
 {
   nsCOMPtr<nsIProfileLock> lock;
 
   nsresult rv = NS_LockProfilePath(aDirectory, nullptr, nullptr,
                                    getter_AddRefs(lock));
@@ -260,16 +272,26 @@ SetTaskbarGroupId(const nsString& aId)
         NS_WARNING("SetCurrentProcessExplicitAppUserModelID failed for child process.");
     }
 
     if (hDLL)
         ::FreeLibrary(hDLL);
 }
 #endif
 
+#ifdef MOZ_NUWA_PROCESS
+void
+OnFinishNuwaPreparation(nsITimer *aTimer, void *aClosure)
+{
+    NS_ASSERTION(MakeNuwaProcess != nullptr,
+		 "MakeNuwaProcess() is not available!");
+    MakeNuwaProcess();
+}
+#endif
+
 nsresult
 XRE_InitChildProcess(int aArgc,
                      char* aArgv[],
                      GeckoProcessType aProcess)
 {
   NS_ENSURE_ARG_MIN(aArgc, 2);
   NS_ENSURE_ARG_POINTER(aArgv);
   NS_ENSURE_ARG_POINTER(aArgv[0]);
@@ -507,16 +529,29 @@ XRE_InitChildProcess(int aArgc,
       }
 
       if (!process->Init()) {
         profiler_shutdown();
         NS_LogTerm();
         return NS_ERROR_FAILURE;
       }
 
+#ifdef MOZ_NUWA_PROCESS
+      nsCOMPtr<nsITimer> timer;
+      if (aProcess == GeckoProcessType_Content &&
+          CommandLine::ForCurrentProcess()->HasSwitch(L"nuwa")) {
+        // Wait the Nuwa process for NUWA_PREPARATION_TIME ms.
+        timer = do_CreateInstance(NS_TIMER_CONTRACTID);
+        rv = timer->InitWithFuncCallback(OnFinishNuwaPreparation,
+                                         nullptr,
+                                         NUWA_PREPARATION_TIME,
+                                         nsITimer::TYPE_ONE_SHOT);
+      }
+#endif
+
       // Run the UI event loop on the main thread.
       uiMessageLoop.MessageLoop::Run();
 
       // Allow ProcessChild to clean up after itself before going out of
       // scope and being deleted
       process->CleanUp();
       mozilla::Omnijar::CleanUp();
     }
--- a/widget/gonk/nsAppShell.cpp
+++ b/widget/gonk/nsAppShell.cpp
@@ -52,16 +52,20 @@
 #include "GonkMemoryPressureMonitoring.h"
 
 #include "android/log.h"
 #include "libui/EventHub.h"
 #include "libui/InputReader.h"
 #include "libui/InputDispatcher.h"
 #include "cutils/properties.h"
 
+#ifdef MOZ_NUWA_PROCESS
+#include "ipc/Nuwa.h"
+#endif
+
 #include "GeckoProfiler.h"
 
 // Defines kKeyMapping and GetKeyNameIndex()
 #include "GonkKeyMapping.h"
 
 #define LOG(args...)                                            \
     __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 #ifdef VERBOSE_LOG_ENABLED
@@ -728,16 +732,21 @@ nsAppShell::Init()
       android::MediaResourceManagerService::instantiate();
     }
 #endif
     nsCOMPtr<nsIObserverService> obsServ = GetObserverService();
     if (obsServ) {
         obsServ->AddObserver(this, "browser-ui-startup-complete", false);
     }
 
+#ifdef MOZ_NUWA_PROCESS
+    // Make sure main thread was woken up after Nuwa fork.
+    NuwaAddConstructor((void (*)(void *))&NotifyEvent, nullptr);
+#endif
+
     // Delay initializing input devices until the screen has been
     // initialized (and we know the resolution).
     return rv;
 }
 
 NS_IMETHODIMP
 nsAppShell::Observe(nsISupports* aSubject,
                     const char* aTopic,