diff options
Diffstat (limited to 'lib/libthr/thread/thr_fork.c')
-rw-r--r-- | lib/libthr/thread/thr_fork.c | 41 |
1 files changed, 22 insertions, 19 deletions
diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c index 8e1ea6a..1ce7c6e 100644 --- a/lib/libthr/thread/thr_fork.c +++ b/lib/libthr/thread/thr_fork.c @@ -89,9 +89,9 @@ _pthread_atfork(void (*prepare)(void), void (*parent)(void), af->prepare = prepare; af->parent = parent; af->child = child; - THR_UMUTEX_LOCK(curthread, &_thr_atfork_lock); + _thr_rwl_rdlock(&_thr_atfork_lock); TAILQ_INSERT_TAIL(&_thr_atfork_list, af, qe); - THR_UMUTEX_UNLOCK(curthread, &_thr_atfork_lock); + _thr_rwl_unlock(&_thr_atfork_lock); return (0); } @@ -104,7 +104,7 @@ __pthread_cxa_finalize(struct dl_phdr_info *phdr_info) _thr_check_init(); curthread = _get_curthread(); - THR_UMUTEX_LOCK(curthread, &_thr_atfork_lock); + _thr_rwl_wrlock(&_thr_atfork_lock); TAILQ_FOREACH_SAFE(af, &_thr_atfork_list, qe, af1) { if (__elf_phdr_match_addr(phdr_info, af->prepare) || __elf_phdr_match_addr(phdr_info, af->parent) || @@ -113,7 +113,7 @@ __pthread_cxa_finalize(struct dl_phdr_info *phdr_info) free(af); } } - THR_UMUTEX_UNLOCK(curthread, &_thr_atfork_lock); + _thr_rwl_unlock(&_thr_atfork_lock); _thr_tsd_unload(phdr_info); _thr_sigact_unload(phdr_info); } @@ -137,7 +137,7 @@ _fork(void) curthread = _get_curthread(); - THR_UMUTEX_LOCK(curthread, &_thr_atfork_lock); + _thr_rwl_rdlock(&_thr_atfork_lock); /* Run down atfork prepare handlers. */ TAILQ_FOREACH_REVERSE(af, &_thr_atfork_list, atfork_head, qe) { @@ -146,6 +146,12 @@ _fork(void) } /* + * Block all signals until we reach a safe point. + */ + _thr_signal_block(curthread); + _thr_signal_prefork(); + + /* * All bets are off as to what should happen soon if the parent * process was not so kindly as to set up pthread fork hooks to * relinquish all running threads. @@ -158,12 +164,6 @@ _fork(void) was_threaded = 0; } - /* - * Block all signals until we reach a safe point. - */ - _thr_signal_block(curthread); - _thr_signal_prefork(); - /* Fork a new process: */ if ((ret = __sys_fork()) == 0) { /* Child process */ @@ -182,7 +182,7 @@ _fork(void) /* clear other threads locked us. */ _thr_umutex_init(&curthread->lock); - _thr_umutex_init(&_thr_atfork_lock); + _mutex_fork(curthread); _thr_signal_postfork_child(); @@ -192,13 +192,12 @@ _fork(void) /* reinitialize libc spinlocks. */ _thr_spinlock_init(); - _mutex_fork(curthread); /* reinitalize library. */ _libpthread_init(curthread); - /* Ready to continue, unblock signals. */ - _thr_signal_unblock(curthread); + /* atfork is reinitializeded by _libpthread_init()! */ + _thr_rwl_rdlock(&_thr_atfork_lock); if (was_threaded) { __isthreaded = 1; @@ -206,32 +205,36 @@ _fork(void) __isthreaded = 0; } + /* Ready to continue, unblock signals. */ + _thr_signal_unblock(curthread); + /* Run down atfork child handlers. */ TAILQ_FOREACH(af, &_thr_atfork_list, qe) { if (af->child != NULL) af->child(); } + _thr_rwlock_unlock(&_thr_atfork_lock); } else { /* Parent process */ errsave = errno; _thr_signal_postfork(); - /* Ready to continue, unblock signals. */ - _thr_signal_unblock(curthread); - if (was_threaded) { _rtld_atfork_post(rtld_locks); _malloc_postfork(); } + /* Ready to continue, unblock signals. */ + _thr_signal_unblock(curthread); + /* Run down atfork parent handlers. */ TAILQ_FOREACH(af, &_thr_atfork_list, qe) { if (af->parent != NULL) af->parent(); } - THR_UMUTEX_UNLOCK(curthread, &_thr_atfork_lock); + _thr_rwlock_unlock(&_thr_atfork_lock); } errno = errsave; |