mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 928995: Move Nuwa to PreallocatedProcessManager. r=bent
This commit is contained in:
parent
59a3ad26e7
commit
1d1cdf444c
@ -121,10 +121,6 @@ using namespace mozilla::system;
|
|||||||
#include "BluetoothService.h"
|
#include "BluetoothService.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
|
||||||
#include "ipc/Nuwa.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "JavaScriptParent.h"
|
#include "JavaScriptParent.h"
|
||||||
|
|
||||||
#ifdef MOZ_B2G_FM
|
#ifdef MOZ_B2G_FM
|
||||||
@ -140,8 +136,6 @@ using namespace mozilla::system;
|
|||||||
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
static NS_DEFINE_CID(kCClipboardCID, NS_CLIPBOARD_CID);
|
||||||
static const char* sClipboardTextFlavors[] = { kUnicodeMime };
|
static const char* sClipboardTextFlavors[] = { kUnicodeMime };
|
||||||
|
|
||||||
#define NUWA_FORK_WAIT_DURATION_MS 2000 // 2 seconds.
|
|
||||||
|
|
||||||
using base::ChildPrivileges;
|
using base::ChildPrivileges;
|
||||||
using base::KillProcess;
|
using base::KillProcess;
|
||||||
using namespace mozilla::dom::bluetooth;
|
using namespace mozilla::dom::bluetooth;
|
||||||
@ -273,32 +267,16 @@ static bool sCanLaunchSubprocesses;
|
|||||||
// The first content child has ID 1, so the chrome process can have ID 0.
|
// The first content child has ID 1, so the chrome process can have ID 0.
|
||||||
static uint64_t gContentChildID = 1;
|
static uint64_t gContentChildID = 1;
|
||||||
|
|
||||||
|
|
||||||
// sNuwaProcess points to the Nuwa process which is used for forking new
|
|
||||||
// processes later.
|
|
||||||
static StaticRefPtr<ContentParent> sNuwaProcess;
|
|
||||||
// Nuwa process is ready for creating new process.
|
|
||||||
static bool sNuwaReady = false;
|
|
||||||
// The array containing the preallocated processes. 4 as the inline storage size
|
|
||||||
// should be enough so we don't need to grow the nsAutoTArray.
|
|
||||||
static StaticAutoPtr<nsAutoTArray<nsRefPtr<ContentParent>, 4> > sSpareProcesses;
|
|
||||||
static StaticAutoPtr<nsTArray<CancelableTask*> > sNuwaForkWaitTasks;
|
|
||||||
|
|
||||||
// We want the prelaunched process to know that it's for apps, but not
|
// We want the prelaunched process to know that it's for apps, but not
|
||||||
// actually for any app in particular. Use a magic manifest URL.
|
// actually for any app in particular. Use a magic manifest URL.
|
||||||
// Can't be a static constant.
|
// Can't be a static constant.
|
||||||
#define MAGIC_PREALLOCATED_APP_MANIFEST_URL NS_LITERAL_STRING("{{template}}")
|
#define MAGIC_PREALLOCATED_APP_MANIFEST_URL NS_LITERAL_STRING("{{template}}")
|
||||||
|
|
||||||
void
|
/* static */ already_AddRefed<ContentParent>
|
||||||
ContentParent::RunNuwaProcess()
|
ContentParent::RunNuwaProcess()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
nsRefPtr<ContentParent> nuwaProcess =
|
||||||
if (sNuwaProcess) {
|
|
||||||
NS_RUNTIMEABORT("sNuwaProcess is created twice.");
|
|
||||||
}
|
|
||||||
|
|
||||||
sNuwaProcess =
|
|
||||||
new ContentParent(/* aApp = */ nullptr,
|
new ContentParent(/* aApp = */ nullptr,
|
||||||
/* aIsForBrowser = */ false,
|
/* aIsForBrowser = */ false,
|
||||||
/* aIsForPreallocated = */ true,
|
/* aIsForPreallocated = */ true,
|
||||||
@ -307,109 +285,10 @@ ContentParent::RunNuwaProcess()
|
|||||||
base::PRIVILEGES_INHERIT,
|
base::PRIVILEGES_INHERIT,
|
||||||
PROCESS_PRIORITY_BACKGROUND,
|
PROCESS_PRIORITY_BACKGROUND,
|
||||||
/* aIsNuwaProcess = */ true);
|
/* aIsNuwaProcess = */ true);
|
||||||
sNuwaProcess->Init();
|
nuwaProcess->Init();
|
||||||
|
return nuwaProcess.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
|
||||||
// initialization off the critical path of app startup.
|
|
||||||
static CancelableTask* sPreallocateAppProcessTask;
|
|
||||||
// This number is fairly arbitrary ... the intention is to put off
|
|
||||||
// launching another app process until the last one has finished
|
|
||||||
// loading its content, to reduce CPU/memory/IO contention.
|
|
||||||
static int sPreallocateDelayMs = 1000;
|
|
||||||
|
|
||||||
static void
|
|
||||||
DelayedNuwaFork()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
sPreallocateAppProcessTask = nullptr;
|
|
||||||
|
|
||||||
if (!sNuwaReady) {
|
|
||||||
if (!sNuwaProcess) {
|
|
||||||
ContentParent::RunNuwaProcess();
|
|
||||||
}
|
|
||||||
// else sNuwaProcess is starting. It will SendNuwaFork() when ready.
|
|
||||||
} else if (sSpareProcesses->IsEmpty()) {
|
|
||||||
sNuwaProcess->SendNuwaFork();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ScheduleDelayedNuwaFork()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (sPreallocateAppProcessTask) {
|
|
||||||
// Make sure there is only one request running.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sPreallocateAppProcessTask = NewRunnableFunction(DelayedNuwaFork);
|
|
||||||
MessageLoop::current()->
|
|
||||||
PostDelayedTask(FROM_HERE,
|
|
||||||
sPreallocateAppProcessTask,
|
|
||||||
sPreallocateDelayMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a spare ContentParent from sSpareProcesses list.
|
|
||||||
*/
|
|
||||||
static already_AddRefed<ContentParent>
|
|
||||||
GetSpareProcess()
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (sSpareProcesses->IsEmpty()) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsRefPtr<ContentParent> process = sSpareProcesses->LastElement();
|
|
||||||
sSpareProcesses->RemoveElementAt(sSpareProcesses->Length() - 1);
|
|
||||||
|
|
||||||
if (sSpareProcesses->IsEmpty() && sNuwaReady) {
|
|
||||||
NS_ASSERTION(sNuwaProcess != nullptr,
|
|
||||||
"Nuwa process is not present!");
|
|
||||||
ScheduleDelayedNuwaFork();
|
|
||||||
}
|
|
||||||
|
|
||||||
return process.forget();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Publish a ContentParent to spare process list.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
PublishSpareProcess(ContentParent* aContent)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (!sNuwaForkWaitTasks->IsEmpty()) {
|
|
||||||
sNuwaForkWaitTasks->ElementAt(0)->Cancel();
|
|
||||||
sNuwaForkWaitTasks->RemoveElementAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
sSpareProcesses->AppendElement(aContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
MaybeForgetSpare(ContentParent* aContent)
|
|
||||||
{
|
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
|
|
||||||
if (sSpareProcesses->RemoveElement(aContent)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (aContent == sNuwaProcess) {
|
|
||||||
sNuwaProcess = nullptr;
|
|
||||||
sNuwaReady = false;
|
|
||||||
ScheduleDelayedNuwaFork();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// PreallocateAppProcess is called by the PreallocatedProcessManager.
|
// PreallocateAppProcess is called by the PreallocatedProcessManager.
|
||||||
// ContentParent then takes this process back within
|
// ContentParent then takes this process back within
|
||||||
// MaybeTakePreallocatedAppProcess.
|
// MaybeTakePreallocatedAppProcess.
|
||||||
@ -433,11 +312,7 @@ ContentParent::MaybeTakePreallocatedAppProcess(const nsAString& aAppManifestURL,
|
|||||||
ChildPrivileges aPrivs,
|
ChildPrivileges aPrivs,
|
||||||
ProcessPriority aInitialPriority)
|
ProcessPriority aInitialPriority)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
|
||||||
nsRefPtr<ContentParent> process = GetSpareProcess();
|
|
||||||
#else
|
|
||||||
nsRefPtr<ContentParent> process = PreallocatedProcessManager::Take();
|
nsRefPtr<ContentParent> process = PreallocatedProcessManager::Take();
|
||||||
#endif
|
|
||||||
if (!process) {
|
if (!process) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -464,17 +339,8 @@ ContentParent::StartUp()
|
|||||||
|
|
||||||
sCanLaunchSubprocesses = true;
|
sCanLaunchSubprocesses = true;
|
||||||
|
|
||||||
sSpareProcesses = new nsAutoTArray<nsRefPtr<ContentParent>, 4>();
|
|
||||||
ClearOnShutdown(&sSpareProcesses);
|
|
||||||
|
|
||||||
sNuwaForkWaitTasks = new nsTArray<CancelableTask*>();
|
|
||||||
ClearOnShutdown(&sNuwaForkWaitTasks);
|
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
|
||||||
ScheduleDelayedNuwaFork();
|
|
||||||
#else
|
|
||||||
// Try to preallocate a process that we can transform into an app later.
|
// Try to preallocate a process that we can transform into an app later.
|
||||||
PreallocatedProcessManager::AllocateAfterDelay();
|
PreallocatedProcessManager::AllocateAfterDelay();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
@ -1027,25 +893,13 @@ ContentParent::MarkAsDead()
|
|||||||
mIsAlive = false;
|
mIsAlive = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
ContentParent::OnNuwaForkTimeout()
|
|
||||||
{
|
|
||||||
if (!sNuwaForkWaitTasks->IsEmpty()) {
|
|
||||||
sNuwaForkWaitTasks->RemoveElementAt(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We haven't RecvAddNewProcess() after SendNuwaFork(). Maybe the main
|
|
||||||
// thread of the Nuwa process is in deadlock.
|
|
||||||
MOZ_ASSERT(false, "Can't fork from the nuwa process.");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ContentParent::OnChannelError()
|
ContentParent::OnChannelError()
|
||||||
{
|
{
|
||||||
nsRefPtr<ContentParent> content(this);
|
nsRefPtr<ContentParent> content(this);
|
||||||
PContentParent::OnChannelError();
|
PContentParent::OnChannelError();
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
MaybeForgetSpare(this);
|
PreallocatedProcessManager::MaybeForgetSpare(this);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1801,19 +1655,12 @@ ContentParent::RecvGetShowPasswordSetting(bool* showPassword)
|
|||||||
bool
|
bool
|
||||||
ContentParent::RecvFirstIdle()
|
ContentParent::RecvFirstIdle()
|
||||||
{
|
{
|
||||||
#ifdef MOZ_NUWA_PROCESS
|
|
||||||
if (sSpareProcesses->IsEmpty() && sNuwaReady) {
|
|
||||||
ScheduleDelayedNuwaFork();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
#else
|
|
||||||
// When the ContentChild goes idle, it sends us a FirstIdle message
|
// When the ContentChild goes idle, it sends us a FirstIdle message
|
||||||
// which we use as a good time to prelaunch another process. If we
|
// which we use as a good time to prelaunch another process. If we
|
||||||
// prelaunch any sooner than this, then we'll be competing with the
|
// prelaunch any sooner than this, then we'll be competing with the
|
||||||
// child process and slowing it down.
|
// child process and slowing it down.
|
||||||
PreallocatedProcessManager::AllocateAfterDelay();
|
PreallocatedProcessManager::AllocateAfterDelay();
|
||||||
return true;
|
return true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1897,34 +1744,16 @@ ContentParent::RecvBroadcastVolume(const nsString& aVolumeName)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
ContentParent::SendNuwaFork()
|
|
||||||
{
|
|
||||||
if (this != sNuwaProcess) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CancelableTask* nuwaForkTimeoutTask = NewRunnableMethod(
|
|
||||||
this, &ContentParent::OnNuwaForkTimeout);
|
|
||||||
sNuwaForkWaitTasks->AppendElement(nuwaForkTimeoutTask);
|
|
||||||
|
|
||||||
MessageLoop::current()->
|
|
||||||
PostDelayedTask(FROM_HERE,
|
|
||||||
nuwaForkTimeoutTask,
|
|
||||||
NUWA_FORK_WAIT_DURATION_MS);
|
|
||||||
|
|
||||||
return PContentParent::SendNuwaFork();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ContentParent::RecvNuwaReady()
|
ContentParent::RecvNuwaReady()
|
||||||
{
|
{
|
||||||
NS_ASSERTION(!sNuwaReady, "Multiple Nuwa processes created!");
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
ProcessPriorityManager::SetProcessPriority(sNuwaProcess,
|
PreallocatedProcessManager::OnNuwaReady();
|
||||||
hal::PROCESS_PRIORITY_FOREGROUND);
|
|
||||||
sNuwaReady = true;
|
|
||||||
SendNuwaFork();
|
|
||||||
return true;
|
return true;
|
||||||
|
#else
|
||||||
|
NS_ERROR("ContentParent::RecvNuwaReady() not implemented!");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
@ -1939,7 +1768,7 @@ ContentParent::RecvAddNewProcess(const uint32_t& aPid,
|
|||||||
aFds,
|
aFds,
|
||||||
base::PRIVILEGES_DEFAULT);
|
base::PRIVILEGES_DEFAULT);
|
||||||
content->Init();
|
content->Init();
|
||||||
PublishSpareProcess(content);
|
PreallocatedProcessManager::PublishSpareProcess(content);
|
||||||
return true;
|
return true;
|
||||||
#else
|
#else
|
||||||
NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
|
NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
|
||||||
|
@ -92,7 +92,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
static already_AddRefed<ContentParent> PreallocateAppProcess();
|
static already_AddRefed<ContentParent> PreallocateAppProcess();
|
||||||
|
|
||||||
static void RunNuwaProcess();
|
static already_AddRefed<ContentParent> RunNuwaProcess();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get or create a content process for the given TabContext. aFrameElement
|
* Get or create a content process for the given TabContext. aFrameElement
|
||||||
@ -209,8 +209,6 @@ public:
|
|||||||
return PContentParent::RecvPJavaScriptConstructor(aActor);
|
return PContentParent::RecvPJavaScriptConstructor(aActor);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool SendNuwaFork();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
|
void OnChannelConnected(int32_t pid) MOZ_OVERRIDE;
|
||||||
virtual void ActorDestroy(ActorDestroyReason why);
|
virtual void ActorDestroy(ActorDestroyReason why);
|
||||||
|
@ -9,6 +9,19 @@
|
|||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/dom/ContentParent.h"
|
#include "mozilla/dom/ContentParent.h"
|
||||||
#include "nsIPropertyBag2.h"
|
#include "nsIPropertyBag2.h"
|
||||||
|
#include "ProcessPriorityManager.h"
|
||||||
|
#include "nsServiceManagerUtils.h"
|
||||||
|
#include "nsCxPusher.h"
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
#include "ipc/Nuwa.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This number is fairly arbitrary ... the intention is to put off
|
||||||
|
// launching another app process until the last one has finished
|
||||||
|
// loading its content, to reduce CPU/memory/IO contention.
|
||||||
|
#define DEFAULT_ALLOCATE_DELAY 1000
|
||||||
|
#define NUWA_FORK_WAIT_DURATION_MS 2000 // 2 seconds.
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::hal;
|
using namespace mozilla::hal;
|
||||||
@ -35,6 +48,31 @@ public:
|
|||||||
void AllocateNow();
|
void AllocateNow();
|
||||||
already_AddRefed<ContentParent> Take();
|
already_AddRefed<ContentParent> Take();
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
public:
|
||||||
|
void ScheduleDelayedNuwaFork();
|
||||||
|
void DelayedNuwaFork();
|
||||||
|
void PublishSpareProcess(ContentParent* aContent);
|
||||||
|
void MaybeForgetSpare(ContentParent* aContent);
|
||||||
|
void OnNuwaReady();
|
||||||
|
already_AddRefed<ContentParent> GetSpareProcess();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnNuwaForkTimeout();
|
||||||
|
void NuwaFork();
|
||||||
|
|
||||||
|
// initialization off the critical path of app startup.
|
||||||
|
CancelableTask* mPreallocateAppProcessTask;
|
||||||
|
|
||||||
|
// The array containing the preallocated processes. 4 as the inline storage size
|
||||||
|
// should be enough so we don't need to grow the nsAutoTArray.
|
||||||
|
nsAutoTArray<nsRefPtr<ContentParent>, 4> mSpareProcesses;
|
||||||
|
nsTArray<CancelableTask*> mNuwaForkWaitTasks;
|
||||||
|
|
||||||
|
// Nuwa process is ready for creating new process.
|
||||||
|
bool mIsNuwaReady;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
|
static mozilla::StaticRefPtr<PreallocatedProcessManagerImpl> sSingleton;
|
||||||
|
|
||||||
@ -72,6 +110,10 @@ NS_IMPL_ISUPPORTS1(PreallocatedProcessManagerImpl, nsIObserver)
|
|||||||
|
|
||||||
PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
|
PreallocatedProcessManagerImpl::PreallocatedProcessManagerImpl()
|
||||||
: mEnabled(false)
|
: mEnabled(false)
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
, mPreallocateAppProcessTask(nullptr)
|
||||||
|
, mIsNuwaReady(false)
|
||||||
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -127,7 +169,11 @@ PreallocatedProcessManagerImpl::Enable()
|
|||||||
}
|
}
|
||||||
|
|
||||||
mEnabled = true;
|
mEnabled = true;
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
ScheduleDelayedNuwaFork();
|
||||||
|
#else
|
||||||
AllocateAfterDelay();
|
AllocateAfterDelay();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -140,7 +186,8 @@ PreallocatedProcessManagerImpl::AllocateAfterDelay()
|
|||||||
MessageLoop::current()->PostDelayedTask(
|
MessageLoop::current()->PostDelayedTask(
|
||||||
FROM_HERE,
|
FROM_HERE,
|
||||||
NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateOnIdle),
|
NewRunnableMethod(this, &PreallocatedProcessManagerImpl::AllocateOnIdle),
|
||||||
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs", 1000));
|
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
|
||||||
|
DEFAULT_ALLOCATE_DELAY));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -165,6 +212,135 @@ PreallocatedProcessManagerImpl::AllocateNow()
|
|||||||
mPreallocatedAppProcess = ContentParent::PreallocateAppProcess();
|
mPreallocatedAppProcess = ContentParent::PreallocateAppProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::ScheduleDelayedNuwaFork()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (mPreallocateAppProcessTask) {
|
||||||
|
// Make sure there is only one request running.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mPreallocateAppProcessTask = NewRunnableMethod(
|
||||||
|
this, &PreallocatedProcessManagerImpl::DelayedNuwaFork);
|
||||||
|
MessageLoop::current()->PostDelayedTask(
|
||||||
|
FROM_HERE, mPreallocateAppProcessTask,
|
||||||
|
Preferences::GetUint("dom.ipc.processPrelaunch.delayMs",
|
||||||
|
DEFAULT_ALLOCATE_DELAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::DelayedNuwaFork()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
mPreallocateAppProcessTask = nullptr;
|
||||||
|
|
||||||
|
if (!mIsNuwaReady) {
|
||||||
|
if (!mPreallocatedAppProcess) {
|
||||||
|
mPreallocatedAppProcess = ContentParent::RunNuwaProcess();
|
||||||
|
}
|
||||||
|
// else mPreallocatedAppProcess is starting. It will NuwaFork() when ready.
|
||||||
|
} else if (mSpareProcesses.IsEmpty()) {
|
||||||
|
NuwaFork();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a spare ContentParent from mSpareProcesses list.
|
||||||
|
*/
|
||||||
|
already_AddRefed<ContentParent>
|
||||||
|
PreallocatedProcessManagerImpl::GetSpareProcess()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (mSpareProcesses.IsEmpty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsRefPtr<ContentParent> process = mSpareProcesses.LastElement();
|
||||||
|
mSpareProcesses.RemoveElementAt(mSpareProcesses.Length() - 1);
|
||||||
|
|
||||||
|
if (mSpareProcesses.IsEmpty() && mIsNuwaReady) {
|
||||||
|
NS_ASSERTION(mPreallocatedAppProcess != nullptr,
|
||||||
|
"Nuwa process is not present!");
|
||||||
|
ScheduleDelayedNuwaFork();
|
||||||
|
}
|
||||||
|
|
||||||
|
return process.forget();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish a ContentParent to spare process list.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::PublishSpareProcess(ContentParent* aContent)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (!mNuwaForkWaitTasks.IsEmpty()) {
|
||||||
|
mNuwaForkWaitTasks.ElementAt(0)->Cancel();
|
||||||
|
mNuwaForkWaitTasks.RemoveElementAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
mSpareProcesses.AppendElement(aContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::MaybeForgetSpare(ContentParent* aContent)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
|
||||||
|
if (mSpareProcesses.RemoveElement(aContent)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aContent == mPreallocatedAppProcess) {
|
||||||
|
mPreallocatedAppProcess = nullptr;
|
||||||
|
mIsNuwaReady = false;
|
||||||
|
ScheduleDelayedNuwaFork();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::OnNuwaReady()
|
||||||
|
{
|
||||||
|
NS_ASSERTION(!mIsNuwaReady, "Multiple Nuwa processes created!");
|
||||||
|
ProcessPriorityManager::SetProcessPriority(mPreallocatedAppProcess,
|
||||||
|
hal::PROCESS_PRIORITY_FOREGROUND);
|
||||||
|
mIsNuwaReady = true;
|
||||||
|
NuwaFork();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::OnNuwaForkTimeout()
|
||||||
|
{
|
||||||
|
if (!mNuwaForkWaitTasks.IsEmpty()) {
|
||||||
|
mNuwaForkWaitTasks.RemoveElementAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We haven't RecvAddNewProcess() after NuwaFork(). Maybe the main
|
||||||
|
// thread of the Nuwa process is in deadlock.
|
||||||
|
MOZ_ASSERT(false, "Can't fork from the nuwa process.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PreallocatedProcessManagerImpl::NuwaFork()
|
||||||
|
{
|
||||||
|
CancelableTask* nuwaForkTimeoutTask = NewRunnableMethod(
|
||||||
|
this, &PreallocatedProcessManagerImpl::OnNuwaForkTimeout);
|
||||||
|
mNuwaForkWaitTasks.AppendElement(nuwaForkTimeoutTask);
|
||||||
|
|
||||||
|
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||||
|
nuwaForkTimeoutTask,
|
||||||
|
NUWA_FORK_WAIT_DURATION_MS);
|
||||||
|
mPreallocatedAppProcess->SendNuwaFork();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
PreallocatedProcessManagerImpl::Disable()
|
PreallocatedProcessManagerImpl::Disable()
|
||||||
{
|
{
|
||||||
@ -174,8 +350,24 @@ PreallocatedProcessManagerImpl::Disable()
|
|||||||
|
|
||||||
mEnabled = false;
|
mEnabled = false;
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
// Cancel pending fork.
|
||||||
|
if (mPreallocateAppProcessTask) {
|
||||||
|
mPreallocateAppProcessTask->Cancel();
|
||||||
|
mPreallocateAppProcessTask = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mPreallocatedAppProcess) {
|
if (mPreallocatedAppProcess) {
|
||||||
mPreallocatedAppProcess->ShutDown();
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
while (mSpareProcesses.Length() > 0){
|
||||||
|
nsRefPtr<ContentParent> process = mSpareProcesses[0];
|
||||||
|
process->Close();
|
||||||
|
mSpareProcesses.RemoveElementAt(0);
|
||||||
|
}
|
||||||
|
mIsNuwaReady = false;
|
||||||
|
#endif
|
||||||
|
mPreallocatedAppProcess->Close();
|
||||||
mPreallocatedAppProcess = nullptr;
|
mPreallocatedAppProcess = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,6 +391,11 @@ PreallocatedProcessManagerImpl::ObserveProcessShutdown(nsISupports* aSubject)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline PreallocatedProcessManagerImpl* GetPPMImpl()
|
||||||
|
{
|
||||||
|
return PreallocatedProcessManagerImpl::Singleton();
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
@ -206,25 +403,53 @@ namespace mozilla {
|
|||||||
/* static */ void
|
/* static */ void
|
||||||
PreallocatedProcessManager::AllocateAfterDelay()
|
PreallocatedProcessManager::AllocateAfterDelay()
|
||||||
{
|
{
|
||||||
PreallocatedProcessManagerImpl::Singleton()->AllocateAfterDelay();
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
GetPPMImpl()->ScheduleDelayedNuwaFork();
|
||||||
|
#else
|
||||||
|
GetPPMImpl()->AllocateAfterDelay();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
PreallocatedProcessManager::AllocateOnIdle()
|
PreallocatedProcessManager::AllocateOnIdle()
|
||||||
{
|
{
|
||||||
PreallocatedProcessManagerImpl::Singleton()->AllocateOnIdle();
|
GetPPMImpl()->AllocateOnIdle();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
PreallocatedProcessManager::AllocateNow()
|
PreallocatedProcessManager::AllocateNow()
|
||||||
{
|
{
|
||||||
PreallocatedProcessManagerImpl::Singleton()->AllocateNow();
|
GetPPMImpl()->AllocateNow();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ already_AddRefed<ContentParent>
|
/* static */ already_AddRefed<ContentParent>
|
||||||
PreallocatedProcessManager::Take()
|
PreallocatedProcessManager::Take()
|
||||||
{
|
{
|
||||||
return PreallocatedProcessManagerImpl::Singleton()->Take();
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
return GetPPMImpl()->GetSpareProcess();
|
||||||
|
#else
|
||||||
|
return GetPPMImpl()->Take();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
/* static */ void
|
||||||
|
PreallocatedProcessManager::PublishSpareProcess(ContentParent* aContent)
|
||||||
|
{
|
||||||
|
GetPPMImpl()->PublishSpareProcess(aContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
PreallocatedProcessManager::MaybeForgetSpare(ContentParent* aContent)
|
||||||
|
{
|
||||||
|
GetPPMImpl()->MaybeForgetSpare(aContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
PreallocatedProcessManager::OnNuwaReady()
|
||||||
|
{
|
||||||
|
GetPPMImpl()->OnNuwaReady();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -78,6 +78,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
static already_AddRefed<ContentParent> Take();
|
static already_AddRefed<ContentParent> Take();
|
||||||
|
|
||||||
|
#ifdef MOZ_NUWA_PROCESS
|
||||||
|
static void PublishSpareProcess(ContentParent* aContent);
|
||||||
|
static void MaybeForgetSpare(ContentParent* aContent);
|
||||||
|
static void OnNuwaReady();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PreallocatedProcessManager();
|
PreallocatedProcessManager();
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager);
|
DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager);
|
||||||
|
Loading…
Reference in New Issue
Block a user