/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set sw=2 ts=2 autoindent cindent expandtab: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef __NUWA_H_ #define __NUWA_H_ #include #include #include "mozilla/Types.h" /** * Nuwa is a goddess who created mankind according to her figure in the * ancient Chinese mythology. */ // Max number of top level protocol that can be handled by Nuwa process. #ifndef NUWA_TOPLEVEL_MAX #define NUWA_TOPLEVEL_MAX 8 #endif struct NuwaProtoFdInfo { int protoId; int originFd; int newFds[2]; }; #define NUWA_NEWFD_PARENT 0 #define NUWA_NEWFD_CHILD 1 extern "C" { /** * The following 3 methods are used to synchronously spawn the Nuwa process. * The typical usage is: * * The IPC thread The main thread * 1. Receives the request. * 2. NuwaSpawnPrepare(). * 3. Request main thread to * spawn. --------------------------------------+ * 4. NuwaSpawnWait(). V * 5. NuwaSpawn() to clone all * the threads in the Nuwa * process (including main * & IPC threads). * 6. NuwaSpawn() finishes and * +-------------------------------------- signals NuwaSpawnWait(). * V * 7. NuwaSpawnWait() returns. */ /** * Prepare for spawning a new process. The calling thread (typically the IPC * thread) will block further requests to spawn a new process. */ MFBT_API void NuwaSpawnPrepare(); /** * Called on the thread that receives the request. Used to wait until * NuwaSpawn() finishes and maintain the stack of the calling thread. */ MFBT_API void NuwaSpawnWait(); /** * Spawn a new content process, called in the Nuwa process. This has to run on * the main thread. * * @return The process ID of the new process. */ MFBT_API pid_t NuwaSpawn(); /** * The following methods are for marking threads created in the Nuwa process so * they can be frozen and then recreated in the spawned process. All threads * except the main thread must be marked by one of the following 4 methods; * otherwise, we have a thread that is created but unknown to us. The Nuwa * process will never become ready and this needs to be fixed. */ /** * Mark the current thread as supporting Nuwa. The thread will implicitly freeze * by calling a blocking method such as pthread_mutex_lock() or epoll_wait(). * * @param recreate The custom function that will be called in the spawned * process, after the thread is recreated. Can be nullptr if no * custom function to be called after the thread is recreated. * Note that this function is called duing thread recreation * while other threads are frozen. It must not perform any * action (e.g. acquiring a mutex) that might depend on another * thread that is still blocked. * @param arg The argument passed to the custom function. Can be nullptr. */ MFBT_API void NuwaMarkCurrentThread(void (*recreate)(void *), void *arg); /** * Mark the current thread as not supporting Nuwa. The calling thread will not * be automatically cloned from the Nuwa process to spawned process. If this * thread needs to be created in the spawned process, use NuwaAddConstructor() * or NuwaAddFinalConstructor() to do it. */ MFBT_API void NuwaSkipCurrentThread(); /** * Force the current thread to freeze explicitly at the current point. */ MFBT_API void NuwaFreezeCurrentThread(); /** * Helper functions for the NuwaCheckpointCurrentThread() macro. */ MFBT_API jmp_buf* NuwaCheckpointCurrentThread1(); MFBT_API bool NuwaCheckpointCurrentThread2(int setjmpCond); /** * Set the point to recover after thread recreation. The calling thread is not * blocked. This is used for the thread that cannot freeze (i.e. the IPC * thread). */ #define NuwaCheckpointCurrentThread() \ NuwaCheckpointCurrentThread2(setjmp(*NuwaCheckpointCurrentThread1())) /** * The following methods are called in the initialization stage of the Nuwa * process. */ /** * Prepare for making the Nuwa process. */ MFBT_API void PrepareNuwaProcess(); /** * Make the current process a Nuwa process. Start to freeze the threads. */ MFBT_API void MakeNuwaProcess(); /** * Register a method to be invoked after a new process is spawned. The method * will be invoked on the main thread *before* recreating the other threads. * The registered method must not perform any action (e.g. acquiring a mutex) * that might depend on another thread that has not yet been recreated. * * @param construct The method to be invoked. * @param arg The argument passed to the method. */ MFBT_API void NuwaAddConstructor(void (*construct)(void *), void *arg); /** * Register a method to be invoked after a new process is spawned and threads * are recreated. The method will be invoked on the main thread *after* * the other threads are recreated and fully functional. * * @param construct The method to be invoked. * @param arg The argument passed to the method. */ MFBT_API void NuwaAddFinalConstructor(void (*construct)(void *), void *arg); /** * Register a method to be invoked after the current thread is recreated in the * spawned process. Note that this function is called while other threads are * frozen. It must not perform any action (e.g. acquiring a mutex) that might * depend on another thread that is still blocked. * * @param construct The method to be invoked. * @param arg The argument passed to the method. */ MFBT_API void NuwaAddThreadConstructor(void (*construct)(void *), void *arg); /** * The methods to query the Nuwa-related states. */ /** * @return If the current process is the Nuwa process. */ MFBT_API bool IsNuwaProcess(); /** * @return If the Nuwa process is ready for spawning new processes. */ MFBT_API bool IsNuwaReady(); #if defined(DEBUG) /** * Asserts that aThread is not frozen. */ MFBT_API void NuwaAssertNotFrozen(unsigned int aThread, const char* aThreadName); #else #define NuwaAssertNotFrozen(aThread, aThreadName) do {} while(0); #endif }; #endif /* __NUWA_H_ */