Bug 771765 - Support template content process, part 6: support re-creation of the threads created in the template process. r=khuey, r=jorendorff

The threads that are frozen/recreated include:
* ImageBridgeChildThread.
* Image decoding thread pool.
* IPC thread (checkpointed, but not frozen).
* GC Helper thread.
* XPC runtime watchdog thread.
* Socket transport service thread/thread pool.
* Memory pressure watcher.
* Timer thread.
* DOM promise worker.
This commit is contained in:
Thinker Lee ext:(%2C%20Cervantes%20Yu%20%3Ccyu%40mozilla.com%3E) 2013-06-03 18:14:42 +08:00
parent e6a13008bc
commit d6da7b763f
13 changed files with 202 additions and 1 deletions

View File

@ -45,6 +45,10 @@
#include "Worker.h"
#include "WorkerPrivate.h"
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
using namespace mozilla;
using namespace mozilla::dom;
@ -893,6 +897,14 @@ public:
NS_IMETHOD
Run()
{
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
"NuwaMarkCurrentThread is undefined!");
NuwaMarkCurrentThread(nullptr, nullptr);
NuwaFreezeCurrentThread();
}
#endif
WorkerPrivate* workerPrivate = mWorkerPrivate;
mWorkerPrivate = nullptr;

View File

@ -361,6 +361,10 @@ ConnectImageBridgeInChildProcess(Transport* aTransport,
ipc::ChildSide);
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
static void ReleaseImageClientNow(ImageClient* aClient)
{
MOZ_ASSERT(InImageBridgeChildThread());
@ -537,6 +541,16 @@ ImageBridgeChild::StartUpInChildProcess(Transport* aTransport,
return false;
}
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
sImageBridgeChildThread
->message_loop()->PostTask(FROM_HERE,
NewRunnableFunction(NuwaMarkCurrentThread,
(void (*)(void *))nullptr,
(void *)nullptr));
}
#endif
sImageBridgeChildSingleton = new ImageBridgeChild();
sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
FROM_HERE,

View File

@ -43,6 +43,10 @@
#include "gfx2DGlue.h"
#include <algorithm>
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
using namespace mozilla;
using namespace mozilla::image;
using namespace mozilla::layers;
@ -3055,6 +3059,37 @@ RasterImage::DecodePool::GetEventTarget()
return target.forget();
}
#ifdef MOZ_NUWA_PROCESS
class RIDThreadPoolListener : public nsIThreadPoolListener
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITHREADPOOLLISTENER
RIDThreadPoolListener() {}
~RIDThreadPoolListener() {}
};
NS_IMPL_ISUPPORTS1(RIDThreadPoolListener, nsIThreadPoolListener)
NS_IMETHODIMP
RIDThreadPoolListener::OnThreadCreated()
{
if (IsNuwaProcess()) {
NuwaMarkCurrentThread((void (*)(void *))nullptr, nullptr);
}
return NS_OK;
}
NS_IMETHODIMP
RIDThreadPoolListener::OnThreadShuttingDown()
{
return NS_OK;
}
#endif // MOZ_NUWA_PROCESS
RasterImage::DecodePool::DecodePool()
: mThreadPoolMutex("Thread Pool")
{
@ -3072,6 +3107,12 @@ RasterImage::DecodePool::DecodePool()
mThreadPool->SetThreadLimit(limit);
mThreadPool->SetIdleThreadLimit(limit);
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
mThreadPool->SetListener(new RIDThreadPoolListener());
}
#endif
nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
if (obsSvc) {
obsSvc->AddObserver(this, "xpcom-shutdown-threads", false);

View File

@ -26,14 +26,35 @@ ChildThread::ChildThread(Thread::Options options)
ChildThread::~ChildThread() {
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
bool ChildThread::Run() {
return StartWithOptions(options_);
bool r = StartWithOptions(options_);
#ifdef MOZ_NUWA_PROCESS
NS_ASSERTION(NuwaMarkCurrentThread, "NuwaMarkCurrentThread is not defined!");
if (IsNuwaProcess()) {
message_loop()->PostTask(FROM_HERE,
NewRunnableFunction(&ChildThread::MarkThread));
}
#endif
return r;
}
void ChildThread::OnChannelError() {
owner_loop_->PostTask(FROM_HERE, new MessageLoop::QuitTask());
}
#ifdef MOZ_NUWA_PROCESS
void ChildThread::MarkThread() {
NuwaMarkCurrentThread(nullptr, nullptr);
if (!NuwaCheckpointCurrentThread()) {
NS_RUNTIMEABORT("Should not be here!");
}
}
#endif
bool ChildThread::Send(IPC::Message* msg) {
if (!channel_.get()) {
delete msg;

View File

@ -61,6 +61,10 @@ class ChildThread : public IPC::Channel::Listener,
virtual void OnMessageReceived(const IPC::Message& msg);
virtual void OnChannelError();
#ifdef MOZ_NUWA_PROCESS
static void MarkThread();
#endif
// The message loop used to run tasks on the thread that started this thread.
MessageLoop* owner_loop_;

View File

@ -4049,6 +4049,10 @@ AC_SUBST(NSPR_CFLAGS)
AC_SUBST(NSPR_LIBS)
AC_SUBST(MOZ_NATIVE_NSPR)
if test -n "$MOZ_NUWA_PROCESS"; then
AC_DEFINE(MOZ_NUWA_PROCESS)
fi
OS_CFLAGS="$CFLAGS"
OS_CXXFLAGS="$CXXFLAGS"
OS_CPPFLAGS="$CPPFLAGS"

View File

@ -2279,11 +2279,26 @@ GCHelperThread::finish()
}
#ifdef JS_THREADSAFE
#ifdef MOZ_NUWA_PROCESS
extern "C" {
MFBT_API bool IsNuwaProcess();
MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void *), void *arg);
}
#endif
/* static */
void
GCHelperThread::threadMain(void *arg)
{
PR_SetCurrentThreadName("JS GC Helper");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess && IsNuwaProcess()) {
JS_ASSERT(NuwaMarkCurrentThread != nullptr);
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
static_cast<GCHelperThread *>(arg)->threadLoop();
}

View File

@ -1022,6 +1022,10 @@ class Watchdog
bool mShuttingDown;
};
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
class WatchdogManager : public nsIObserver
{
public:
@ -1155,6 +1159,15 @@ WatchdogMain(void *arg)
{
PR_SetCurrentThreadName("JS Watchdog");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
"NuwaMarkCurrentThread is undefined!");
NuwaMarkCurrentThread(nullptr, nullptr);
NuwaFreezeCurrentThread();
}
#endif
Watchdog* self = static_cast<Watchdog*>(arg);
WatchdogManager* manager = self->Manager();

View File

@ -634,11 +634,23 @@ nsSocketTransportService::AfterProcessNextEvent(nsIThreadInternal* thread,
return NS_OK;
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
NS_IMETHODIMP
nsSocketTransportService::Run()
{
PR_SetCurrentThreadName("Socket Thread");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
"NuwaMarkCurrentThread is undefined!");
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
SOCKET_LOG(("STS thread init\n"));
psm::InitializeSSLServerCertVerificationThreads();

View File

@ -425,6 +425,38 @@ nsOutputStreamTransport::IsNonBlocking(bool *result)
return NS_OK;
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
class STSThreadPoolListener : public nsIThreadPoolListener
{
public:
NS_DECL_THREADSAFE_ISUPPORTS
NS_DECL_NSITHREADPOOLLISTENER
STSThreadPoolListener() {}
~STSThreadPoolListener() {}
};
NS_IMPL_ISUPPORTS1(STSThreadPoolListener, nsIThreadPoolListener)
NS_IMETHODIMP
STSThreadPoolListener::OnThreadCreated()
{
if (IsNuwaProcess()) {
NuwaMarkCurrentThread(nullptr, nullptr);
}
return NS_OK;
}
NS_IMETHODIMP
STSThreadPoolListener::OnThreadShuttingDown()
{
return NS_OK;
}
#endif // MOZ_NUWA_PROCESS
//-----------------------------------------------------------------------------
// nsStreamTransportService
//-----------------------------------------------------------------------------
@ -445,6 +477,11 @@ nsStreamTransportService::Init()
mPool->SetThreadLimit(25);
mPool->SetIdleThreadLimit(1);
mPool->SetIdleThreadTimeout(PR_SecondsToInterval(30));
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
mPool->SetListener(new STSThreadPoolListener());
}
#endif
nsCOMPtr<nsIObserverService> obsSvc =
mozilla::services::GetObserverService();

View File

@ -21,6 +21,10 @@
#define LOG(args...) \
__android_log_print(ANDROID_LOG_INFO, "GonkMemoryPressure" , ## args)
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
using namespace mozilla;
namespace {
@ -113,6 +117,14 @@ public:
{
MOZ_ASSERT(!NS_IsMainThread());
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
"NuwaMarkCurrentThread is undefined!");
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
int lowMemFd = open("/sys/kernel/mm/lowmemkiller/notify_trigger_active",
O_RDONLY | O_CLOEXEC);
NS_ENSURE_STATE(lowMemFd != -1);

View File

@ -893,6 +893,10 @@ enum ccType {
ShutdownCC /* Shutdown CC, used for finding leaks. */
};
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
////////////////////////////////////////////////////////////////////////
// Top level structure for the cycle collector.
////////////////////////////////////////////////////////////////////////

View File

@ -159,11 +159,23 @@ nsresult TimerThread::Shutdown()
return NS_OK;
}
#ifdef MOZ_NUWA_PROCESS
#include "ipc/Nuwa.h"
#endif
/* void Run(); */
NS_IMETHODIMP TimerThread::Run()
{
PR_SetCurrentThreadName("Timer");
#ifdef MOZ_NUWA_PROCESS
if (IsNuwaProcess()) {
NS_ASSERTION(NuwaMarkCurrentThread != nullptr,
"NuwaMarkCurrentThread is undefined!");
NuwaMarkCurrentThread(nullptr, nullptr);
}
#endif
MonitorAutoLock lock(mMonitor);
// We need to know how many microseconds give a positive PRIntervalTime. This