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