mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1091533, Part 2: Implement NuwaAddThreadConstructor() to allow a thread to perform a custom action after being recreated in the content process. r=khuey,tlee
This commit is contained in:
parent
4199f3e652
commit
66f8cbe724
@ -117,6 +117,22 @@ static size_t getPageSize(void) {
|
||||
|
||||
#define NATIVE_THREAD_NAME_LENGTH 16
|
||||
|
||||
typedef struct nuwa_construct {
|
||||
typedef void(*construct_t)(void*);
|
||||
|
||||
construct_t construct;
|
||||
void *arg;
|
||||
|
||||
nuwa_construct(construct_t aConstruct, void *aArg)
|
||||
: construct(aConstruct)
|
||||
, arg(aArg)
|
||||
{ }
|
||||
|
||||
nuwa_construct(const nuwa_construct&) = default;
|
||||
nuwa_construct& operator=(const nuwa_construct&) = default;
|
||||
|
||||
} nuwa_construct_t;
|
||||
|
||||
struct thread_info : public mozilla::LinkedListElement<thread_info> {
|
||||
pthread_t origThreadID;
|
||||
pthread_t recreatedThreadID;
|
||||
@ -131,8 +147,15 @@ struct thread_info : public mozilla::LinkedListElement<thread_info> {
|
||||
|
||||
// The thread specific function to recreate the new thread. It's executed
|
||||
// after the thread is recreated.
|
||||
void (*recrFunc)(void *arg);
|
||||
void *recrArg;
|
||||
|
||||
std::vector<nuwa_construct_t> *recrFunctions;
|
||||
void addThreadConstructor(const nuwa_construct_t *construct) {
|
||||
if (!recrFunctions) {
|
||||
recrFunctions = new std::vector<nuwa_construct_t>();
|
||||
}
|
||||
|
||||
recrFunctions->push_back(*construct);
|
||||
}
|
||||
|
||||
TLSInfoList tlsInfo;
|
||||
|
||||
@ -169,8 +192,12 @@ static thread_info_t *sCurrentRecreatingThread = nullptr;
|
||||
static void
|
||||
RunCustomRecreation() {
|
||||
thread_info_t *tinfo = sCurrentRecreatingThread;
|
||||
if (tinfo->recrFunc != nullptr) {
|
||||
tinfo->recrFunc(tinfo->recrArg);
|
||||
if (tinfo->recrFunctions) {
|
||||
for (auto iter = tinfo->recrFunctions->begin();
|
||||
iter != tinfo->recrFunctions->end();
|
||||
iter++) {
|
||||
iter->construct(iter->arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -189,11 +216,6 @@ RunCustomRecreation() {
|
||||
#define TINFO_FLAG_NUWA_SKIP 0x2
|
||||
#define TINFO_FLAG_NUWA_EXPLICIT_CHECKPOINT 0x4
|
||||
|
||||
typedef struct nuwa_construct {
|
||||
void (*construct)(void *);
|
||||
void *arg;
|
||||
} nuwa_construct_t;
|
||||
|
||||
static std::vector<nuwa_construct_t> sConstructors;
|
||||
static std::vector<nuwa_construct_t> sFinalConstructors;
|
||||
|
||||
@ -507,8 +529,7 @@ thread_info_new(void) {
|
||||
/* link tinfo to sAllThreads */
|
||||
thread_info_t *tinfo = new thread_info_t();
|
||||
tinfo->flags = 0;
|
||||
tinfo->recrFunc = nullptr;
|
||||
tinfo->recrArg = nullptr;
|
||||
tinfo->recrFunctions = nullptr;
|
||||
tinfo->recreatedThreadID = 0;
|
||||
tinfo->recreatedNativeThreadID = 0;
|
||||
tinfo->condMutex = nullptr;
|
||||
@ -556,6 +577,10 @@ thread_info_cleanup(void *arg) {
|
||||
tinfo->remove();
|
||||
pthread_mutex_unlock(&sThreadCountLock);
|
||||
|
||||
if (tinfo->recrFunctions) {
|
||||
delete tinfo->recrFunctions;
|
||||
}
|
||||
|
||||
// while sThreadCountLock is held, since delete calls wrapped functions
|
||||
// which try to lock sThreadCountLock. This results in deadlock. And we
|
||||
// need to delete |tinfo| before decreasing sThreadCount, so Nuwa won't
|
||||
@ -1765,8 +1790,10 @@ NuwaMarkCurrentThread(void (*recreate)(void *), void *arg) {
|
||||
}
|
||||
|
||||
tinfo->flags |= TINFO_FLAG_NUWA_SUPPORT;
|
||||
tinfo->recrFunc = recreate;
|
||||
tinfo->recrArg = arg;
|
||||
if (recreate) {
|
||||
nuwa_construct_t construct(recreate, arg);
|
||||
tinfo->addThreadConstructor(&construct);
|
||||
}
|
||||
|
||||
// XXX Thread name might be set later than this call. If this is the case, we
|
||||
// might need to delay getting the thread name.
|
||||
@ -1873,9 +1900,7 @@ NuwaCheckpointCurrentThread2(int setjmpCond) {
|
||||
*/
|
||||
MFBT_API void
|
||||
NuwaAddConstructor(void (*construct)(void *), void *arg) {
|
||||
nuwa_construct_t ctr;
|
||||
ctr.construct = construct;
|
||||
ctr.arg = arg;
|
||||
nuwa_construct_t ctr(construct, arg);
|
||||
sConstructors.push_back(ctr);
|
||||
}
|
||||
|
||||
@ -1885,12 +1910,21 @@ NuwaAddConstructor(void (*construct)(void *), void *arg) {
|
||||
*/
|
||||
MFBT_API void
|
||||
NuwaAddFinalConstructor(void (*construct)(void *), void *arg) {
|
||||
nuwa_construct_t ctr;
|
||||
ctr.construct = construct;
|
||||
ctr.arg = arg;
|
||||
nuwa_construct_t ctr(construct, arg);
|
||||
sFinalConstructors.push_back(ctr);
|
||||
}
|
||||
|
||||
MFBT_API void
|
||||
NuwaAddThreadConstructor(void (*aConstruct)(void *), void *aArg) {
|
||||
thread_info *tinfo = CUR_THREAD_INFO;
|
||||
if (!tinfo || !aConstruct) {
|
||||
return;
|
||||
}
|
||||
|
||||
nuwa_construct_t construct(aConstruct, aArg);
|
||||
tinfo->addThreadConstructor(&construct);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the current process is the nuwa process.
|
||||
*/
|
||||
|
@ -88,6 +88,10 @@ MFBT_API pid_t NuwaSpawn();
|
||||
* @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);
|
||||
@ -137,22 +141,38 @@ 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.
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user