1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
17 #include <sys/epoll.h>
18 #include <sys/types.h>
19 #include <sys/socket.h>
23 #include "mozilla/LinkedList.h"
26 using namespace mozilla
;
29 * Provides the wrappers to a selected set of pthread and system-level functions
30 * as the basis for implementing Zygote-like preforking mechanism.
34 * Real functions for the wrappers.
37 int __real_pthread_create(pthread_t
*thread
,
38 const pthread_attr_t
*attr
,
39 void *(*start_routine
) (void *),
41 int __real_pthread_key_create(pthread_key_t
*key
, void (*destructor
)(void*));
42 int __real_pthread_key_delete(pthread_key_t key
);
43 pthread_t
__real_pthread_self();
44 int __real_pthread_join(pthread_t thread
, void **retval
);
45 int __real_epoll_wait(int epfd
,
46 struct epoll_event
*events
,
49 int __real_pthread_cond_wait(pthread_cond_t
*cond
, pthread_mutex_t
*mtx
);
50 int __real_pthread_cond_timedwait(pthread_cond_t
*cond
,
52 const struct timespec
*abstime
);
53 int __real___pthread_cond_timedwait(pthread_cond_t
*cond
,
55 const struct timespec
*abstime
,
57 int __real_pthread_mutex_lock(pthread_mutex_t
*mtx
);
58 int __real_poll(struct pollfd
*fds
, nfds_t nfds
, int timeout
);
59 int __real_epoll_create(int size
);
60 int __real_socketpair(int domain
, int type
, int protocol
, int sv
[2]);
61 int __real_pipe2(int __pipedes
[2], int flags
);
62 int __real_pipe(int __pipedes
[2]);
63 int __real_epoll_ctl(int aEpollFd
, int aOp
, int aFd
, struct epoll_event
*aEvent
);
64 int __real_close(int aFd
);
68 #define REAL(s) __real_##s
71 * A Nuwa process is started by preparing. After preparing, it waits
72 * for all threads becoming frozen. Then, it is ready while all
75 static bool sIsNuwaProcess
= false; // This process is a Nuwa process.
76 static bool sIsFreezing
= false; // Waiting for all threads getting frozen.
77 static bool sNuwaReady
= false; // Nuwa process is ready.
78 static bool sNuwaPendingSpawn
= false; // Are there any pending spawn requests?
79 static bool sNuwaForking
= false;
81 // Fds of transports of top level protocols.
82 static NuwaProtoFdInfo sProtoFdInfos
[NUWA_TOPLEVEL_MAX
];
83 static int sProtoFdInfosSize
= 0;
86 struct LibcAllocator
: public std::allocator
<T
>
90 void* libcHandle
= dlopen("libc.so", RTLD_LAZY
);
91 mMallocImpl
= reinterpret_cast<void*(*)(size_t)>(dlsym(libcHandle
, "malloc"));
92 mFreeImpl
= reinterpret_cast<void(*)(void*)>(dlsym(libcHandle
, "free"));
94 if (!(mMallocImpl
&& mFreeImpl
)) {
95 // libc should be available, or we'll deadlock in using TLSInfoList.
100 inline typename
std::allocator
<T
>::pointer
101 allocate(typename
std::allocator
<T
>::size_type n
,
104 return reinterpret_cast<T
*>(mMallocImpl(n
));
108 deallocate(typename
std::allocator
<T
>::pointer p
,
109 typename
std::allocator
<T
>::size_type n
)
117 typedef LibcAllocator
<U
> other
;
120 void* (*mMallocImpl
)(size_t);
121 void (*mFreeImpl
)(void*);
125 * TLSInfoList should use malloc() and free() in libc to avoid the deadlock that
126 * jemalloc calls into __wrap_pthread_mutex_lock() and then deadlocks while
127 * the same thread already acquired sThreadCountLock.
129 typedef std::vector
<std::pair
<pthread_key_t
, void *>,
130 LibcAllocator
<std::pair
<pthread_key_t
, void *> > >
134 * The stack size is chosen carefully so the frozen threads doesn't consume too
135 * much memory in the Nuwa process. The threads shouldn't run deep recursive
136 * methods or do large allocations on the stack to avoid stack overflow.
138 #ifndef NUWA_STACK_SIZE
139 #define NUWA_STACK_SIZE (1024 * 32)
142 struct thread_info
: public mozilla::LinkedListElement
<thread_info
> {
143 pthread_t origThreadID
;
144 pthread_t recreatedThreadID
;
145 pthread_attr_t threadAttr
;
151 void *(*startupFunc
)(void *arg
);
154 // The thread specific function to recreate the new thread. It's executed
155 // after the thread is recreated.
156 void (*recrFunc
)(void *arg
);
161 pthread_mutex_t
*reacquireMutex
;
165 typedef struct thread_info thread_info_t
;
167 static thread_info_t
*sCurrentRecreatingThread
= NULL
;
170 * This function runs the custom recreation function registered when calling
171 * NuwaMarkCurrentThread() after thread stack is restored.
174 RunCustomRecreation() {
175 thread_info_t
*tinfo
= sCurrentRecreatingThread
;
176 if (tinfo
->recrFunc
!= NULL
) {
177 tinfo
->recrFunc(tinfo
->recrArg
);
182 * Every thread should be marked as either TINFO_FLAG_NUWA_SUPPORT or
183 * TINFO_FLAG_NUWA_SKIP, or it means a potential error. We force
184 * Gecko code to mark every single thread to make sure there are no accidents
185 * when recreating threads with Nuwa.
187 * Threads marked as TINFO_FLAG_NUWA_SUPPORT can be checkpointed explicitly, by
188 * calling NuwaCheckpointCurrentThread(), or implicitly when they call into wrapped
189 * functions like pthread_mutex_lock(), epoll_wait(), etc.
190 * TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT denotes the explicitly checkpointed thread.
192 #define TINFO_FLAG_NUWA_SUPPORT 0x1
193 #define TINFO_FLAG_NUWA_SKIP 0x2
194 #define TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT 0x4
196 typedef struct nuwa_construct
{
197 void (*construct
)(void *);
201 static std::vector
<nuwa_construct_t
> sConstructors
;
202 static std::vector
<nuwa_construct_t
> sFinalConstructors
;
204 typedef std::map
<pthread_key_t
, void (*)(void *)> TLSKeySet
;
205 static TLSKeySet sTLSKeys
;
208 * This mutex is used to block the running threads and freeze their contexts.
209 * PrepareNuwaProcess() is the first one to acquire the lock. Further attempts
210 * to acquire this mutex (in the freeze point macros) will block and freeze the
213 static pthread_mutex_t sThreadFreezeLock
= PTHREAD_MUTEX_INITIALIZER
;
215 static LinkedList
<thread_info_t
> sAllThreads
;
216 static int sThreadCount
= 0;
217 static int sThreadFreezeCount
= 0;
219 * This mutex protects the access to thread info:
220 * sAllThreads, sThreadCount, sThreadFreezeCount, sRecreateVIPCount.
222 static pthread_mutex_t sThreadCountLock
= PTHREAD_MUTEX_INITIALIZER
;
224 * This condition variable lets MakeNuwaProcess() wait until all recreated
225 * threads are frozen.
227 static pthread_cond_t sThreadChangeCond
= PTHREAD_COND_INITIALIZER
;
230 * This mutex and condition variable is used to serialize the fork requests
231 * from the parent process.
233 static pthread_mutex_t sForkLock
= PTHREAD_MUTEX_INITIALIZER
;
234 static pthread_cond_t sForkWaitCond
= PTHREAD_COND_INITIALIZER
;
237 * sForkWaitCondChanged will be reset to false on the IPC thread before
238 * and will be changed to true on the main thread to indicate that the condition
239 * that the IPC thread is waiting for has already changed.
241 static bool sForkWaitCondChanged
= false;
244 * This mutex protects the access to sTLSKeys, which keeps track of existing
247 static pthread_mutex_t sTLSKeyLock
= PTHREAD_MUTEX_INITIALIZER
;
248 static int sThreadSkipCount
= 0;
250 static thread_info_t
*
251 GetThreadInfoInner(pthread_t threadID
) {
252 for (thread_info_t
*tinfo
= sAllThreads
.getFirst();
254 tinfo
= tinfo
->getNext()) {
255 if (pthread_equal(tinfo
->origThreadID
, threadID
)) {
264 * Get thread info using the specified thread ID.
266 * @return thread_info_t which has threadID == specified threadID
268 static thread_info_t
*
269 GetThreadInfo(pthread_t threadID
) {
270 if (sIsNuwaProcess
) {
271 REAL(pthread_mutex_lock
)(&sThreadCountLock
);
273 thread_info_t
*tinfo
= GetThreadInfoInner(threadID
);
274 if (sIsNuwaProcess
) {
275 pthread_mutex_unlock(&sThreadCountLock
);
280 #if !defined(HAVE_THREAD_TLS_KEYWORD)
282 * Get thread info of the current thread.
284 * @return thread_info_t for the current thread.
286 static thread_info_t
*
288 pthread_t threadID
= REAL(pthread_self
)();
289 pthread_t
thread_info_t::*threadIDptr
=
291 &thread_info_t::origThreadID
:
292 &thread_info_t::recreatedThreadID
);
294 REAL(pthread_mutex_lock
)(&sThreadCountLock
);
295 thread_info_t
*tinfo
;
296 for (tinfo
= sAllThreads
.getFirst();
298 tinfo
= tinfo
->getNext()) {
299 if (pthread_equal(tinfo
->*threadIDptr
, threadID
)) {
303 pthread_mutex_unlock(&sThreadCountLock
);
306 #define CUR_THREAD_INFO GetCurThreadInfo()
307 #define SET_THREAD_INFO(x) /* Nothing to do. */
309 // Is not NULL only for threads created by pthread_create() in an Nuwa process.
310 // It is always NULL for the main thread.
311 static __thread thread_info_t
*sCurThreadInfo
= NULL
;
312 #define CUR_THREAD_INFO sCurThreadInfo
313 #define SET_THREAD_INFO(x) do { sCurThreadInfo = (x); } while(0)
314 #endif // HAVE_THREAD_TLS_KEYWORD
317 * Track all epoll fds and handling events.
323 typedef struct epoll_event Events
;
324 typedef std::map
<int, Events
> EpollEventsMap
;
325 typedef EpollEventsMap::iterator iterator
;
326 typedef EpollEventsMap::const_iterator const_iterator
;
328 EpollInfo(): mBackSize(0) {}
329 EpollInfo(int aBackSize
): mBackSize(aBackSize
) {}
330 EpollInfo(const EpollInfo
&aOther
): mEvents(aOther
.mEvents
)
331 , mBackSize(aOther
.mBackSize
) {
337 void AddEvents(int aFd
, Events
&aEvents
) {
338 std::pair
<iterator
, bool> pair
=
339 mEvents
.insert(std::make_pair(aFd
, aEvents
));
345 void RemoveEvents(int aFd
) {
346 if (!mEvents
.erase(aFd
)) {
351 void ModifyEvents(int aFd
, Events
&aEvents
) {
352 iterator it
= mEvents
.find(aFd
);
353 if (it
== mEvents
.end()) {
356 it
->second
= aEvents
;
359 const Events
&FindEvents(int aFd
) const {
360 const_iterator it
= mEvents
.find(aFd
);
361 if (it
== mEvents
.end()) {
367 int Size() const { return mEvents
.size(); }
369 // Iterator with values of <fd, Events> pairs.
370 const_iterator
begin() const { return mEvents
.begin(); }
371 const_iterator
end() const { return mEvents
.end(); }
373 int BackSize() const { return mBackSize
; }
376 EpollEventsMap mEvents
;
379 friend class EpollManager
;
382 typedef std::map
<int, EpollInfo
> EpollInfoMap
;
383 typedef EpollInfoMap::iterator iterator
;
384 typedef EpollInfoMap::const_iterator const_iterator
;
387 void AddEpollInfo(int aEpollFd
, int aBackSize
) {
388 EpollInfo
*oldinfo
= FindEpollInfo(aEpollFd
);
389 if (oldinfo
!= NULL
) {
392 mEpollFdsInfo
[aEpollFd
] = EpollInfo(aBackSize
);
395 EpollInfo
*FindEpollInfo(int aEpollFd
) {
396 iterator it
= mEpollFdsInfo
.find(aEpollFd
);
397 if (it
== mEpollFdsInfo
.end()) {
403 void RemoveEpollInfo(int aEpollFd
) {
404 if (!mEpollFdsInfo
.erase(aEpollFd
)) {
409 int Size() const { return mEpollFdsInfo
.size(); }
411 // Iterator of <epollfd, EpollInfo> pairs.
412 const_iterator
begin() const { return mEpollFdsInfo
.begin(); }
413 const_iterator
end() const { return mEpollFdsInfo
.end(); }
415 static EpollManager
*Singleton() {
417 sInstance
= new EpollManager();
422 static void Shutdown() {
432 static EpollManager
*sInstance
;
434 mEpollFdsInfo
.clear();
437 EpollInfoMap mEpollFdsInfo
;
442 EpollManager
* EpollManager::sInstance
;
444 static thread_info_t
*
445 thread_info_new(void) {
446 /* link tinfo to sAllThreads */
447 thread_info_t
*tinfo
= new thread_info_t();
449 tinfo
->recrFunc
= NULL
;
450 tinfo
->recrArg
= NULL
;
451 tinfo
->recreatedThreadID
= 0;
452 tinfo
->reacquireMutex
= NULL
;
453 tinfo
->stk
= malloc(NUWA_STACK_SIZE
);
454 pthread_attr_init(&tinfo
->threadAttr
);
456 REAL(pthread_mutex_lock
)(&sThreadCountLock
);
457 // Insert to the tail.
458 sAllThreads
.insertBack(tinfo
);
461 pthread_cond_signal(&sThreadChangeCond
);
462 pthread_mutex_unlock(&sThreadCountLock
);
468 thread_info_cleanup(void *arg
) {
470 // We shouldn't have any thread exiting when we are forking a new process.
474 thread_info_t
*tinfo
= (thread_info_t
*)arg
;
475 pthread_attr_destroy(&tinfo
->threadAttr
);
477 REAL(pthread_mutex_lock
)(&sThreadCountLock
);
478 /* unlink tinfo from sAllThreads */
482 pthread_cond_signal(&sThreadChangeCond
);
483 pthread_mutex_unlock(&sThreadCountLock
);
490 _thread_create_startup(void *arg
) {
491 thread_info_t
*tinfo
= (thread_info_t
*)arg
;
494 // Save thread info; especially, stackaddr & stacksize.
495 // Reuse the stack in the new thread.
496 pthread_getattr_np(REAL(pthread_self
)(), &tinfo
->threadAttr
);
498 SET_THREAD_INFO(tinfo
);
499 tinfo
->origThreadID
= REAL(pthread_self
)();
501 pthread_cleanup_push(thread_info_cleanup
, tinfo
);
503 r
= tinfo
->startupFunc(tinfo
->startupArg
);
505 if (!sIsNuwaProcess
) {
509 pthread_cleanup_pop(1);
514 // reserve STACK_RESERVED_SZ * 4 bytes for thread_recreate_startup().
515 #define STACK_RESERVED_SZ 64
516 #define STACK_SENTINEL(v) ((v)[0])
517 #define STACK_SENTINEL_VALUE(v) ((uint32_t)(v) ^ 0xdeadbeef)
520 thread_create_startup(void *arg
) {
522 * Dark Art!! Never try to do the same unless you are ABSOLUTELY sure of
523 * what you are doing!
525 * This function is here for reserving stack space before calling
526 * _thread_create_startup(). see also thread_create_startup();
529 volatile uint32_t reserved
[STACK_RESERVED_SZ
];
531 // Reserve stack space.
532 STACK_SENTINEL(reserved
) = STACK_SENTINEL_VALUE(reserved
);
534 r
= _thread_create_startup(arg
);
536 // Check if the reservation is enough.
537 if (STACK_SENTINEL(reserved
) != STACK_SENTINEL_VALUE(reserved
)) {
538 abort(); // Did not reserve enough stack space.
541 thread_info_t
*tinfo
= CUR_THREAD_INFO
;
542 if (!sIsNuwaProcess
) {
543 longjmp(tinfo
->retEnv
, 1);
552 extern "C" MFBT_API
int
553 __wrap_pthread_create(pthread_t
*thread
,
554 const pthread_attr_t
*attr
,
555 void *(*start_routine
) (void *),
557 if (!sIsNuwaProcess
) {
558 return REAL(pthread_create
)(thread
, attr
, start_routine
, arg
);
561 thread_info_t
*tinfo
= thread_info_new();
562 tinfo
->startupFunc
= start_routine
;
563 tinfo
->startupArg
= arg
;
564 pthread_attr_setstack(&tinfo
->threadAttr
, tinfo
->stk
, NUWA_STACK_SIZE
);
566 int rv
= REAL(pthread_create
)(thread
,
568 thread_create_startup
,
571 thread_info_cleanup(tinfo
);
573 tinfo
->origThreadID
= *thread
;
582 * Iterates over the existing TLS keys and store the TLS data for the current
586 SaveTLSInfo(thread_info_t
*tinfo
) {
587 REAL(pthread_mutex_lock
)(&sTLSKeyLock
);
588 tinfo
->tlsInfo
.clear();
589 for (TLSKeySet::const_iterator it
= sTLSKeys
.begin();
590 it
!= sTLSKeys
.end();
592 void *value
= pthread_getspecific(it
->first
);
597 pthread_key_t key
= it
->first
;
598 tinfo
->tlsInfo
.push_back(TLSInfoList::value_type(key
, value
));
600 pthread_mutex_unlock(&sTLSKeyLock
);
604 * Restores the TLS data for the current thread from tinfo.
607 RestoreTLSInfo(thread_info_t
*tinfo
) {
610 for (TLSInfoList::const_iterator it
= tinfo
->tlsInfo
.begin();
611 it
!= tinfo
->tlsInfo
.end();
613 pthread_key_t key
= it
->first
;
614 const void *value
= it
->second
;
615 if (pthread_setspecific(key
, value
)) {
620 SET_THREAD_INFO(tinfo
);
621 tinfo
->recreatedThreadID
= REAL(pthread_self
)();
624 extern "C" MFBT_API
int
625 __wrap_pthread_key_create(pthread_key_t
*key
, void (*destructor
)(void*)) {
626 int rv
= REAL(pthread_key_create
)(key
, destructor
);
630 REAL(pthread_mutex_lock
)(&sTLSKeyLock
);
631 sTLSKeys
.insert(TLSKeySet::value_type(*key
, destructor
));
632 pthread_mutex_unlock(&sTLSKeyLock
);
636 extern "C" MFBT_API
int
637 __wrap_pthread_key_delete(pthread_key_t key
) {
638 if (!sIsNuwaProcess
) {
639 return REAL(pthread_key_delete
)(key
);
641 int rv
= REAL(pthread_key_delete
)(key
);
645 REAL(pthread_mutex_lock
)(&sTLSKeyLock
);
647 pthread_mutex_unlock(&sTLSKeyLock
);
651 extern "C" MFBT_API pthread_t
652 __wrap_pthread_self() {
653 thread_info_t
*tinfo
= CUR_THREAD_INFO
;
655 // For recreated thread, masquerade as the original thread in the Nuwa
657 return tinfo
->origThreadID
;
659 return REAL(pthread_self
)();
662 extern "C" MFBT_API
int
663 __wrap_pthread_join(pthread_t thread
, void **retval
) {
664 thread_info_t
*tinfo
= GetThreadInfo(thread
);
666 return REAL(pthread_join
)(thread
, retval
);
668 // pthread_join() need to use the real thread ID in the spawned process.
669 return REAL(pthread_join
)(tinfo
->recreatedThreadID
, retval
);
673 * The following are used to synchronize between the main thread and the
674 * thread being recreated. The main thread will wait until the thread is woken
675 * up from the freeze points or the blocking intercepted functions and then
676 * proceed to recreate the next frozen thread.
678 * In thread recreation, the main thread recreates the frozen threads one by
679 * one. The recreated threads will be "gated" until the main thread "opens the
680 * gate" to let them run freely as if they were created from scratch. The VIP
681 * threads gets the chance to run first after their thread stacks are recreated
682 * (using longjmp()) so they can adjust their contexts to a valid, consistent
683 * state. The threads frozen waiting for pthread condition variables are VIP
684 * threads. After woken up they need to run first to make the associated mutex
685 * in a valid state to maintain the semantics of the intercepted function calls
686 * (like pthread_cond_wait()).
689 // Used to synchronize the main thread and the thread being recreated so that
690 // only one thread is allowed to be recreated at a time.
691 static pthread_mutex_t sRecreateWaitLock
= PTHREAD_MUTEX_INITIALIZER
;
692 // Used to block recreated threads until the main thread "opens the gate".
693 static pthread_mutex_t sRecreateGateLock
= PTHREAD_MUTEX_INITIALIZER
;
694 // Used to block the main thread from "opening the gate" until all VIP threads
695 // have been recreated.
696 static pthread_mutex_t sRecreateVIPGateLock
= PTHREAD_MUTEX_INITIALIZER
;
697 static pthread_cond_t sRecreateVIPCond
= PTHREAD_COND_INITIALIZER
;
698 static int sRecreateVIPCount
= 0;
699 static int sRecreateGatePassed
= 0;
702 * Thread recreation macros.
704 * The following macros are used in the forked process to synchronize and
705 * control the progress of thread recreation.
707 * 1. RECREATE_START() is first called in the beginning of thread
708 * recreation to set sRecreateWaitLock and sRecreateGateLock in locked
710 * 2. For each frozen thread:
711 * 2.1. RECREATE_BEFORE() to set the thread being recreated.
712 * 2.2. thread_recreate() to recreate the frozen thread.
713 * 2.3. Main thread calls RECREATE_WAIT() to wait on sRecreateWaitLock until
714 * the thread is recreated from the freeze point and calls
715 * RECREATE_CONTINUE() to release sRecreateWaitLock.
716 * 2.3. Non-VIP threads are blocked on RECREATE_GATE(). VIP threads calls
717 * RECREATE_PASS_VIP() to mark that a VIP thread is successfully
718 * recreated and then is blocked by calling RECREATE_GATE_VIP().
719 * 3. RECREATE_WAIT_ALL_VIP() to wait until all VIP threads passed, that is,
720 * VIP threads already has their contexts (mainly pthread mutex) in a valid
722 * 4. RECREATE_OPEN_GATE() to unblock threads blocked by sRecreateGateLock.
723 * 5. RECREATE_FINISH() to complete thread recreation.
725 #define RECREATE_START() \
727 REAL(pthread_mutex_lock)(&sRecreateWaitLock); \
728 REAL(pthread_mutex_lock)(&sRecreateGateLock); \
730 #define RECREATE_BEFORE(info) do { sCurrentRecreatingThread = info; } while(0)
731 #define RECREATE_WAIT() REAL(pthread_mutex_lock)(&sRecreateWaitLock)
732 #define RECREATE_CONTINUE() do { \
733 RunCustomRecreation(); \
734 pthread_mutex_unlock(&sRecreateWaitLock); \
736 #define RECREATE_FINISH() pthread_mutex_unlock(&sRecreateWaitLock)
737 #define RECREATE_GATE() \
739 REAL(pthread_mutex_lock)(&sRecreateGateLock); \
740 sRecreateGatePassed++; \
741 pthread_mutex_unlock(&sRecreateGateLock); \
743 #define RECREATE_OPEN_GATE() pthread_mutex_unlock(&sRecreateGateLock)
744 #define RECREATE_GATE_VIP() \
746 REAL(pthread_mutex_lock)(&sRecreateGateLock); \
747 pthread_mutex_unlock(&sRecreateGateLock); \
749 #define RECREATE_PASS_VIP() \
751 REAL(pthread_mutex_lock)(&sRecreateVIPGateLock); \
752 sRecreateGatePassed++; \
753 pthread_cond_signal(&sRecreateVIPCond); \
754 pthread_mutex_unlock(&sRecreateVIPGateLock); \
756 #define RECREATE_WAIT_ALL_VIP() \
758 REAL(pthread_mutex_lock)(&sRecreateVIPGateLock); \
759 while(sRecreateGatePassed < sRecreateVIPCount) { \
760 REAL(pthread_cond_wait)(&sRecreateVIPCond, \
761 &sRecreateVIPGateLock); \
763 pthread_mutex_unlock(&sRecreateVIPGateLock); \
767 * Thread freeze points. Note that the freeze points are implemented as macros
768 * so as not to garble the content of the stack after setjmp().
770 * In the nuwa process, when a thread supporting nuwa calls a wrapper
771 * function, freeze point 1 setjmp()s to save the state. We only allow the
772 * thread to be frozen in the wrapper functions. If thread freezing is not
773 * enabled yet, the wrapper functions act like their wrapped counterparts,
774 * except for the extra actions in the freeze points. If thread freezing is
775 * enabled, the thread will be frozen by calling one of the wrapper functions.
776 * The threads can be frozen in any of the following points:
778 * 1) Freeze point 1: this is the point where we setjmp() in the nuwa process
779 * and longjmp() in the spawned process. If freezing is enabled, then the
780 * current thread blocks by acquiring an already locked mutex,
782 * 2) The wrapped function: the function that might block waiting for some
783 * resource or condition.
784 * 3) Freeze point 2: blocks the current thread by acquiring sThreadFreezeLock.
785 * If freezing is not enabled then revert the counter change in freeze
788 #define THREAD_FREEZE_POINT1() \
789 bool freezeCountChg = false; \
790 bool recreated = false; \
791 volatile bool freezePoint2 = false; \
792 thread_info_t *tinfo; \
793 if (sIsNuwaProcess && \
794 (tinfo = CUR_THREAD_INFO) && \
795 (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) && \
796 !(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) { \
797 if (!setjmp(tinfo->jmpEnv)) { \
798 REAL(pthread_mutex_lock)(&sThreadCountLock); \
799 SaveTLSInfo(tinfo); \
800 sThreadFreezeCount++; \
801 freezeCountChg = true; \
802 pthread_cond_signal(&sThreadChangeCond); \
803 pthread_mutex_unlock(&sThreadCountLock); \
806 REAL(pthread_mutex_lock)(&sThreadFreezeLock); \
807 /* Never return from the pthread_mutex_lock() call. */ \
811 RECREATE_CONTINUE(); \
813 freezeCountChg = false; \
818 #define THREAD_FREEZE_POINT1_VIP() \
819 bool freezeCountChg = false; \
820 bool recreated = false; \
821 volatile bool freezePoint1 = false; \
822 volatile bool freezePoint2 = false; \
823 thread_info_t *tinfo; \
824 if (sIsNuwaProcess && \
825 (tinfo = CUR_THREAD_INFO) && \
826 (tinfo->flags & TINFO_FLAG_NUWA_SUPPORT) && \
827 !(tinfo->flags & TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT)) { \
828 if (!setjmp(tinfo->jmpEnv)) { \
829 REAL(pthread_mutex_lock)(&sThreadCountLock); \
830 SaveTLSInfo(tinfo); \
831 sThreadFreezeCount++; \
832 sRecreateVIPCount++; \
833 freezeCountChg = true; \
834 pthread_cond_signal(&sThreadChangeCond); \
835 pthread_mutex_unlock(&sThreadCountLock); \
838 freezePoint1 = true; \
839 REAL(pthread_mutex_lock)(&sThreadFreezeLock); \
840 /* Never return from the pthread_mutex_lock() call. */ \
844 freezeCountChg = false; \
849 #define THREAD_FREEZE_POINT2() \
850 if (freezeCountChg) { \
851 REAL(pthread_mutex_lock)(&sThreadCountLock); \
852 if (sNuwaReady && sIsNuwaProcess) { \
853 pthread_mutex_unlock(&sThreadCountLock); \
854 freezePoint2 = true; \
855 REAL(pthread_mutex_lock)(&sThreadFreezeLock); \
856 /* Never return from the pthread_mutex_lock() call. */ \
859 sThreadFreezeCount--; \
860 pthread_cond_signal(&sThreadChangeCond); \
861 pthread_mutex_unlock(&sThreadCountLock); \
864 #define THREAD_FREEZE_POINT2_VIP() \
865 if (freezeCountChg) { \
866 REAL(pthread_mutex_lock)(&sThreadCountLock); \
867 if (sNuwaReady && sIsNuwaProcess) { \
868 pthread_mutex_unlock(&sThreadCountLock); \
869 freezePoint2 = true; \
870 REAL(pthread_mutex_lock)(&sThreadFreezeLock); \
871 /* Never return from the pthread_mutex_lock() call. */ \
874 sThreadFreezeCount--; \
875 sRecreateVIPCount--; \
876 pthread_cond_signal(&sThreadChangeCond); \
877 pthread_mutex_unlock(&sThreadCountLock); \
881 * Wrapping the blocking functions: epoll_wait(), poll(), pthread_mutex_lock(),
882 * pthread_cond_wait() and pthread_cond_timedwait():
884 * These functions are wrapped by the above freeze point macros. Once a new
885 * process is forked, the recreated thread will be blocked in one of the wrapper
886 * functions. When recreating the thread, we longjmp() to
887 * THREAD_FREEZE_POINT1() to recover the thread stack. Care must be taken to
888 * maintain the semantics of the wrapped function:
890 * - epoll_wait() and poll(): just retry the function.
891 * - pthread_mutex_lock(): don't lock if frozen at freeze point 2 (lock is
893 * - pthread_cond_wait() and pthread_cond_timedwait(): if the thread is frozen
894 * waiting the condition variable, the mutex is already released, we need to
895 * reacquire the mutex before calling the wrapped function again so the mutex
896 * will be in a valid state.
899 extern "C" MFBT_API
int
900 __wrap_epoll_wait(int epfd
,
901 struct epoll_event
*events
,
906 THREAD_FREEZE_POINT1();
907 rv
= REAL(epoll_wait
)(epfd
, events
, maxevents
, timeout
);
908 THREAD_FREEZE_POINT2();
913 extern "C" MFBT_API
int
914 __wrap_pthread_cond_wait(pthread_cond_t
*cond
,
915 pthread_mutex_t
*mtx
) {
918 THREAD_FREEZE_POINT1_VIP();
925 if (recreated
&& mtx
) {
926 if (!freezePoint1
&& pthread_mutex_trylock(mtx
)) {
927 // The thread was frozen in pthread_cond_wait() after releasing mtx in the
928 // Nuwa process. In recreating this thread, We failed to reacquire mtx
929 // with the pthread_mutex_trylock() call, that is, mtx was acquired by
930 // another thread. Because of this, we need the main thread's help to
931 // reacquire mtx so that it will be in a valid state.
932 tinfo
->reacquireMutex
= mtx
;
937 rv
= REAL(pthread_cond_wait
)(cond
, mtx
);
938 if (recreated
&& mtx
) {
939 // We still need to be gated as not to acquire another mutex associated with
940 // another VIP thread and interfere with it.
943 THREAD_FREEZE_POINT2_VIP();
948 extern "C" MFBT_API
int
949 __wrap_pthread_cond_timedwait(pthread_cond_t
*cond
,
950 pthread_mutex_t
*mtx
,
951 const struct timespec
*abstime
) {
954 THREAD_FREEZE_POINT1_VIP();
961 if (recreated
&& mtx
) {
962 if (!freezePoint1
&& pthread_mutex_trylock(mtx
)) {
963 tinfo
->reacquireMutex
= mtx
;
968 rv
= REAL(pthread_cond_timedwait
)(cond
, mtx
, abstime
);
969 if (recreated
&& mtx
) {
972 THREAD_FREEZE_POINT2_VIP();
977 extern "C" int __pthread_cond_timedwait(pthread_cond_t
*cond
,
978 pthread_mutex_t
*mtx
,
979 const struct timespec
*abstime
,
982 extern "C" MFBT_API
int
983 __wrap___pthread_cond_timedwait(pthread_cond_t
*cond
,
984 pthread_mutex_t
*mtx
,
985 const struct timespec
*abstime
,
989 THREAD_FREEZE_POINT1_VIP();
996 if (recreated
&& mtx
) {
997 if (!freezePoint1
&& pthread_mutex_trylock(mtx
)) {
998 tinfo
->reacquireMutex
= mtx
;
1000 RECREATE_CONTINUE();
1001 RECREATE_PASS_VIP();
1003 rv
= REAL(__pthread_cond_timedwait
)(cond
, mtx
, abstime
, clock
);
1004 if (recreated
&& mtx
) {
1005 RECREATE_GATE_VIP();
1007 THREAD_FREEZE_POINT2_VIP();
1012 extern "C" MFBT_API
int
1013 __wrap_pthread_mutex_lock(pthread_mutex_t
*mtx
) {
1016 THREAD_FREEZE_POINT1();
1020 rv
= REAL(pthread_mutex_lock
)(mtx
);
1021 THREAD_FREEZE_POINT2();
1026 extern "C" MFBT_API
int
1027 __wrap_poll(struct pollfd
*fds
, nfds_t nfds
, int timeout
) {
1030 THREAD_FREEZE_POINT1();
1031 rv
= REAL(poll
)(fds
, nfds
, timeout
);
1032 THREAD_FREEZE_POINT2();
1037 extern "C" MFBT_API
int
1038 __wrap_epoll_create(int size
) {
1039 int epollfd
= REAL(epoll_create
)(size
);
1041 if (!sIsNuwaProcess
) {
1046 EpollManager::Singleton()->AddEpollInfo(epollfd
, size
);
1053 * Wrapping the functions to create file descriptor pairs. In the child process
1054 * FD pairs are created for intra-process signaling. The generation of FD pairs
1055 * need to be tracked in the nuwa process so they can be recreated in the
1072 * Protects the access to sSingalFds.
1074 static pthread_mutex_t sSignalFdLock
= PTHREAD_MUTEX_INITIALIZER
;
1075 static std::vector
<FdPairInfo
> sSignalFds
;
1077 extern "C" MFBT_API
int
1078 __wrap_socketpair(int domain
, int type
, int protocol
, int sv
[2])
1080 int rv
= REAL(socketpair
)(domain
, type
, protocol
, sv
);
1082 if (!sIsNuwaProcess
|| rv
< 0) {
1086 REAL(pthread_mutex_lock
)(&sSignalFdLock
);
1087 FdPairInfo signalFd
;
1088 signalFd
.call
= FdPairInfo::kSocketpair
;
1089 signalFd
.FDs
[0] = sv
[0];
1090 signalFd
.FDs
[1] = sv
[1];
1091 signalFd
.domain
= domain
;
1092 signalFd
.type
= type
;
1093 signalFd
.protocol
= protocol
;
1095 sSignalFds
.push_back(signalFd
);
1096 pthread_mutex_unlock(&sSignalFdLock
);
1101 extern "C" MFBT_API
int
1102 __wrap_pipe2(int __pipedes
[2], int flags
)
1104 int rv
= REAL(pipe2
)(__pipedes
, flags
);
1105 if (!sIsNuwaProcess
|| rv
< 0) {
1109 REAL(pthread_mutex_lock
)(&sSignalFdLock
);
1110 FdPairInfo signalFd
;
1111 signalFd
.call
= FdPairInfo::kPipe
;
1112 signalFd
.FDs
[0] = __pipedes
[0];
1113 signalFd
.FDs
[1] = __pipedes
[1];
1114 signalFd
.flags
= flags
;
1115 sSignalFds
.push_back(signalFd
);
1116 pthread_mutex_unlock(&sSignalFdLock
);
1120 extern "C" MFBT_API
int
1121 __wrap_pipe(int __pipedes
[2])
1123 return __wrap_pipe2(__pipedes
, 0);
1127 DupeSingleFd(int newFd
, int origFd
)
1130 if (fstat(origFd
, &sb
)) {
1131 // Maybe the original FD is closed.
1134 int fd
= fcntl(origFd
, F_GETFD
);
1135 int fl
= fcntl(origFd
, F_GETFL
);
1136 dup2(newFd
, origFd
);
1137 fcntl(origFd
, F_SETFD
, fd
);
1138 fcntl(origFd
, F_SETFL
, fl
);
1142 extern "C" MFBT_API
void
1145 for (std::vector
<FdPairInfo
>::iterator it
= sSignalFds
.begin();
1146 it
< sSignalFds
.end(); ++it
) {
1150 case FdPairInfo::kPipe
:
1151 rc
= REAL(pipe2
)(fds
, it
->flags
);
1153 case FdPairInfo::kSocketpair
:
1154 rc
= REAL(socketpair
)(it
->domain
, it
->type
, it
->protocol
, fds
);
1161 DupeSingleFd(fds
[0], it
->FDs
[0]);
1162 DupeSingleFd(fds
[1], it
->FDs
[1]);
1167 extern "C" MFBT_API
int
1168 __wrap_epoll_ctl(int aEpollFd
, int aOp
, int aFd
, struct epoll_event
*aEvent
) {
1169 int rv
= REAL(epoll_ctl
)(aEpollFd
, aOp
, aFd
, aEvent
);
1171 if (!sIsNuwaProcess
|| rv
== -1) {
1175 EpollManager::EpollInfo
*info
=
1176 EpollManager::Singleton()->FindEpollInfo(aEpollFd
);
1183 info
->AddEvents(aFd
, *aEvent
);
1187 info
->ModifyEvents(aFd
, *aEvent
);
1191 info
->RemoveEvents(aFd
);
1201 // XXX: thinker: Maybe, we should also track dup, dup2, and other functions.
1202 extern "C" MFBT_API
int
1203 __wrap_close(int aFd
) {
1204 int rv
= REAL(close
)(aFd
);
1205 if (!sIsNuwaProcess
|| rv
== -1) {
1209 EpollManager::EpollInfo
*info
=
1210 EpollManager::Singleton()->FindEpollInfo(aFd
);
1212 EpollManager::Singleton()->RemoveEpollInfo(aFd
);
1219 thread_recreate_startup(void *arg
) {
1221 * Dark Art!! Never do the same unless you are ABSOLUTELY sure what you are
1224 * The stack space collapsed by this frame had been reserved by
1225 * thread_create_startup(). And thread_create_startup() will
1226 * return immediately after returning from real start routine, so
1227 * all collapsed values does not affect the result.
1229 * All outer frames of thread_create_startup() and
1230 * thread_recreate_startup() are equivalent, so
1231 * thread_create_startup() will return successfully.
1233 thread_info_t
*tinfo
= (thread_info_t
*)arg
;
1235 RestoreTLSInfo(tinfo
);
1237 if (setjmp(tinfo
->retEnv
) != 0) {
1241 // longjump() to recreate the stack on the new thread.
1242 longjmp(tinfo
->jmpEnv
, 1);
1251 * Recreate the context given by tinfo at a new thread.
1254 thread_recreate(thread_info_t
*tinfo
) {
1257 // Note that the thread_recreate_startup() runs on the stack specified by
1259 pthread_create(&thread
, &tinfo
->threadAttr
, thread_recreate_startup
, tinfo
);
1263 * Recreate all threads in a process forked from an Nuwa process.
1267 sIsNuwaProcess
= false;
1268 sIsFreezing
= false;
1270 // Run registered constructors.
1271 for (std::vector
<nuwa_construct_t
>::iterator ctr
= sConstructors
.begin();
1272 ctr
!= sConstructors
.end();
1274 (*ctr
).construct((*ctr
).arg
);
1276 sConstructors
.clear();
1278 REAL(pthread_mutex_lock
)(&sThreadCountLock
);
1279 thread_info_t
*tinfo
= sAllThreads
.getFirst();
1280 pthread_mutex_unlock(&sThreadCountLock
);
1283 while (tinfo
!= NULL
) {
1284 if (tinfo
->flags
& TINFO_FLAG_NUWA_SUPPORT
) {
1285 RECREATE_BEFORE(tinfo
);
1286 thread_recreate(tinfo
);
1288 if (tinfo
->reacquireMutex
) {
1289 REAL(pthread_mutex_lock
)(tinfo
->reacquireMutex
);
1291 } else if(!(tinfo
->flags
& TINFO_FLAG_NUWA_SKIP
)) {
1292 // An unmarked thread is found other than the main thread.
1294 // All threads should be marked as one of SUPPORT or SKIP, or
1295 // abort the process to make sure all threads in the Nuwa
1296 // process are Nuwa-aware.
1300 tinfo
= tinfo
->getNext();
1302 RECREATE_WAIT_ALL_VIP();
1303 RECREATE_OPEN_GATE();
1307 // Run registered final constructors.
1308 for (std::vector
<nuwa_construct_t
>::iterator ctr
= sFinalConstructors
.begin();
1309 ctr
!= sFinalConstructors
.end();
1311 (*ctr
).construct((*ctr
).arg
);
1313 sFinalConstructors
.clear();
1319 * Recreate all epoll fds and restore status; include all events.
1322 RecreateEpollFds() {
1323 EpollManager
*man
= EpollManager::Singleton();
1325 for (EpollManager::const_iterator info_it
= man
->begin();
1326 info_it
!= man
->end();
1328 int epollfd
= info_it
->first
;
1329 const EpollManager::EpollInfo
*info
= &info_it
->second
;
1331 int fdflags
= fcntl(epollfd
, F_GETFD
);
1332 if (fdflags
== -1) {
1335 int fl
= fcntl(epollfd
, F_GETFL
);
1340 int newepollfd
= REAL(epoll_create
)(info
->BackSize());
1341 if (newepollfd
== -1) {
1344 int rv
= REAL(close
)(epollfd
);
1348 rv
= dup2(newepollfd
, epollfd
);
1352 rv
= REAL(close
)(newepollfd
);
1357 rv
= fcntl(epollfd
, F_SETFD
, fdflags
);
1361 rv
= fcntl(epollfd
, F_SETFL
, fl
);
1366 for (EpollManager::EpollInfo::const_iterator events_it
= info
->begin();
1367 events_it
!= info
->end();
1369 int fd
= events_it
->first
;
1371 events
= events_it
->second
;
1372 rv
= REAL(epoll_ctl
)(epollfd
, EPOLL_CTL_ADD
, fd
, &events
);
1379 // Shutdown EpollManager. It won't be needed in the spawned process.
1380 EpollManager::Shutdown();
1384 * Fix IPC to make it ready.
1386 * Especially, fix ContentChild.
1389 ReplaceIPC(NuwaProtoFdInfo
*aInfoList
, int aInfoSize
) {
1393 for (i
= 0; i
< aInfoSize
; i
++) {
1394 int fd
= fcntl(aInfoList
[i
].originFd
, F_GETFD
);
1399 int fl
= fcntl(aInfoList
[i
].originFd
, F_GETFL
);
1404 rv
= dup2(aInfoList
[i
].newFds
[NUWA_NEWFD_CHILD
], aInfoList
[i
].originFd
);
1409 rv
= fcntl(aInfoList
[i
].originFd
, F_SETFD
, fd
);
1414 rv
= fcntl(aInfoList
[i
].originFd
, F_SETFL
, fl
);
1422 * Add a new content process at the chrome process.
1425 AddNewProcess(pid_t pid
, NuwaProtoFdInfo
*aInfoList
, int aInfoSize
) {
1426 static bool (*AddNewIPCProcess
)(pid_t
, NuwaProtoFdInfo
*, int) = NULL
;
1428 if (AddNewIPCProcess
== NULL
) {
1429 AddNewIPCProcess
= (bool (*)(pid_t
, NuwaProtoFdInfo
*, int))
1430 dlsym(RTLD_DEFAULT
, "AddNewIPCProcess");
1432 AddNewIPCProcess(pid
, aInfoList
, aInfoSize
);
1436 PrepareProtoSockets(NuwaProtoFdInfo
*aInfoList
, int aInfoSize
) {
1440 for (i
= 0; i
< aInfoSize
; i
++) {
1441 rv
= REAL(socketpair
)(PF_UNIX
, SOCK_STREAM
, 0, aInfoList
[i
].newFds
);
1449 CloseAllProtoSockets(NuwaProtoFdInfo
*aInfoList
, int aInfoSize
) {
1452 for (i
= 0; i
< aInfoSize
; i
++) {
1453 REAL(close
)(aInfoList
[i
].newFds
[0]);
1454 REAL(close
)(aInfoList
[i
].newFds
[1]);
1459 * Fork a new process that is ready for running IPC.
1461 * @return the PID of the new process.
1467 REAL(pthread_mutex_lock
)(&sForkLock
);
1469 PrepareProtoSockets(sProtoFdInfos
, sProtoFdInfosSize
);
1471 sNuwaForking
= true;
1473 sNuwaForking
= false;
1480 AddNewProcess(pid
, sProtoFdInfos
, sProtoFdInfosSize
);
1481 CloseAllProtoSockets(sProtoFdInfos
, sProtoFdInfosSize
);
1484 #ifdef NUWA_DEBUG_CHILD_PROCESS
1485 fprintf(stderr
, "\n\n DEBUG ME @%d\n\n", getpid());
1489 ReplaceIPC(sProtoFdInfos
, sProtoFdInfosSize
);
1492 CloseAllProtoSockets(sProtoFdInfos
, sProtoFdInfosSize
);
1495 sForkWaitCondChanged
= true;
1496 pthread_cond_signal(&sForkWaitCond
);
1497 pthread_mutex_unlock(&sForkLock
);
1503 * Prepare for spawning a new process. Called on the IPC thread.
1506 NuwaSpawnPrepare() {
1507 REAL(pthread_mutex_lock
)(&sForkLock
);
1509 sForkWaitCondChanged
= false; // Will be modified on the main thread.
1513 * Let IPC thread wait until fork action on the main thread has completed.
1517 while (!sForkWaitCondChanged
) {
1518 REAL(pthread_cond_wait
)(&sForkWaitCond
, &sForkLock
);
1520 pthread_mutex_unlock(&sForkLock
);
1524 * Spawn a new process. If not ready for spawn (still waiting for some threads
1525 * to freeze), postpone the spawn request until ready.
1527 * @return the pid of the new process, or 0 if not ready.
1531 if (gettid() != getpid()) {
1532 // Not the main thread.
1539 pid
= ForkIPCProcess();
1541 sNuwaPendingSpawn
= true;
1548 * Prepare to freeze the Nuwa-supporting threads.
1551 PrepareNuwaProcess() {
1552 sIsNuwaProcess
= true;
1553 // Explicitly ignore SIGCHLD so we don't have to call watpid() to reap
1554 // dead child processes.
1555 signal(SIGCHLD
, SIG_IGN
);
1557 // Make marked threads block in one freeze point.
1558 REAL(pthread_mutex_lock
)(&sThreadFreezeLock
);
1561 // Make current process as a Nuwa process.
1564 void (*GetProtoFdInfos
)(NuwaProtoFdInfo
*, int, int *) = NULL
;
1565 void (*OnNuwaProcessReady
)() = NULL
;
1568 REAL(pthread_mutex_lock
)(&sThreadCountLock
);
1570 // wait until all threads are frozen.
1571 while ((sThreadFreezeCount
+ sThreadSkipCount
) != sThreadCount
) {
1572 REAL(pthread_cond_wait
)(&sThreadChangeCond
, &sThreadCountLock
);
1575 GetProtoFdInfos
= (void (*)(NuwaProtoFdInfo
*, int, int *))
1576 dlsym(RTLD_DEFAULT
, "GetProtoFdInfos");
1577 GetProtoFdInfos(sProtoFdInfos
, NUWA_TOPLEVEL_MAX
, &sProtoFdInfosSize
);
1581 pthread_mutex_unlock(&sThreadCountLock
);
1583 OnNuwaProcessReady
= (void (*)())dlsym(RTLD_DEFAULT
, "OnNuwaProcessReady");
1584 OnNuwaProcessReady();
1586 if (sNuwaPendingSpawn
) {
1587 sNuwaPendingSpawn
= false;
1593 * Mark the current thread as supporting Nuwa. The thread will be recreated in
1594 * the spawned process.
1597 NuwaMarkCurrentThread(void (*recreate
)(void *), void *arg
) {
1598 if (!sIsNuwaProcess
) {
1602 thread_info_t
*tinfo
= CUR_THREAD_INFO
;
1603 if (tinfo
== NULL
) {
1607 tinfo
->flags
|= TINFO_FLAG_NUWA_SUPPORT
;
1608 tinfo
->recrFunc
= recreate
;
1609 tinfo
->recrArg
= arg
;
1613 * Mark the current thread as not supporting Nuwa. Don't recreate this thread in
1614 * the spawned process.
1617 NuwaSkipCurrentThread() {
1618 if (!sIsNuwaProcess
) return;
1620 thread_info_t
*tinfo
= CUR_THREAD_INFO
;
1621 if (tinfo
== NULL
) {
1625 if (!(tinfo
->flags
& TINFO_FLAG_NUWA_SKIP
)) {
1628 tinfo
->flags
|= TINFO_FLAG_NUWA_SKIP
;
1632 * Force to freeze the current thread.
1634 * This method does not return in Nuwa process. It returns for the
1638 NuwaFreezeCurrentThread() {
1639 thread_info_t
*tinfo
= CUR_THREAD_INFO
;
1640 if (sIsNuwaProcess
&&
1641 (tinfo
= CUR_THREAD_INFO
) &&
1642 (tinfo
->flags
& TINFO_FLAG_NUWA_SUPPORT
)) {
1643 if (!setjmp(tinfo
->jmpEnv
)) {
1644 REAL(pthread_mutex_lock
)(&sThreadCountLock
);
1646 sThreadFreezeCount
++;
1647 pthread_cond_signal(&sThreadChangeCond
);
1648 pthread_mutex_unlock(&sThreadCountLock
);
1650 REAL(pthread_mutex_lock
)(&sThreadFreezeLock
);
1652 RECREATE_CONTINUE();
1659 * The caller of NuwaCheckpointCurrentThread() is at the line it wishes to
1660 * return after the thread is recreated.
1662 * The checkpointed thread will restart at the calling line of
1663 * NuwaCheckpointCurrentThread(). This macro returns true in the Nuwa process
1664 * and false on the recreated thread in the forked process.
1666 * NuwaCheckpointCurrentThread() is implemented as a macro so we can place the
1667 * setjmp() call in the calling method without changing its stack pointer. This
1668 * is essential for not corrupting the stack when the calling thread continues
1669 * to request the main thread for forking a new process. The caller of
1670 * NuwaCheckpointCurrentThread() should not return before the process forking
1673 * @return true for Nuwa process, and false in the forked process.
1676 NuwaCheckpointCurrentThread1() {
1677 thread_info_t
*tinfo
= CUR_THREAD_INFO
;
1678 if (sIsNuwaProcess
&&
1679 (tinfo
= CUR_THREAD_INFO
) &&
1680 (tinfo
->flags
& TINFO_FLAG_NUWA_SUPPORT
)) {
1681 return &tinfo
->jmpEnv
;
1688 NuwaCheckpointCurrentThread2(int setjmpCond
) {
1689 thread_info_t
*tinfo
= CUR_THREAD_INFO
;
1690 if (setjmpCond
== 0) {
1691 REAL(pthread_mutex_lock
)(&sThreadCountLock
);
1692 if (!(tinfo
->flags
& TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT
)) {
1693 tinfo
->flags
|= TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT
;
1695 sThreadFreezeCount
++;
1697 pthread_cond_signal(&sThreadChangeCond
);
1698 pthread_mutex_unlock(&sThreadCountLock
);
1701 RECREATE_CONTINUE();
1703 return false; // Recreated thread.
1707 * Register methods to be invoked before recreating threads in the spawned
1711 NuwaAddConstructor(void (*construct
)(void *), void *arg
) {
1712 nuwa_construct_t ctr
;
1713 ctr
.construct
= construct
;
1715 sConstructors
.push_back(ctr
);
1719 * Register methods to be invoked after recreating threads in the spawned
1723 NuwaAddFinalConstructor(void (*construct
)(void *), void *arg
) {
1724 nuwa_construct_t ctr
;
1725 ctr
.construct
= construct
;
1727 sFinalConstructors
.push_back(ctr
);
1731 * @return if the current process is the nuwa process.
1735 return sIsNuwaProcess
;
1739 * @return if the nuwa process is ready for spawning new processes.