diff options
author | davidxu <davidxu@FreeBSD.org> | 2010-09-01 03:11:21 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2010-09-01 03:11:21 +0000 |
commit | 5f00b957aee7c4cc6138734e4b4dc582cf4d10f9 (patch) | |
tree | 121f43c8c92789442e82ae22a69ea70be4586b0a /lib/libthr/thread/thr_fork.c | |
parent | 4dcb50723aa0d3f4264ee1d9ca3baf70b4adc2de (diff) | |
download | FreeBSD-src-5f00b957aee7c4cc6138734e4b4dc582cf4d10f9.zip FreeBSD-src-5f00b957aee7c4cc6138734e4b4dc582cf4d10f9.tar.gz |
Change atfork lock from mutex to rwlock, also make mutexes used by malloc()
module private type, when private type mutex is locked/unlocked, thread
critical region is entered or leaved. These changes makes fork()
async-signal safe which required by POSIX. Note that user's atfork handler
still needs to be async-signal safe, but it is not problem of libthr, it
is user's responsiblity.
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; |