diff options
Diffstat (limited to 'lib/libthr/thread')
-rw-r--r-- | lib/libthr/thread/Makefile.inc | 1 | ||||
-rw-r--r-- | lib/libthr/thread/thr_barrier.c | 5 | ||||
-rw-r--r-- | lib/libthr/thread/thr_clean.c | 2 | ||||
-rw-r--r-- | lib/libthr/thread/thr_create.c | 8 | ||||
-rw-r--r-- | lib/libthr/thread/thr_ctrdtr.c | 56 | ||||
-rw-r--r-- | lib/libthr/thread/thr_fork.c | 6 | ||||
-rw-r--r-- | lib/libthr/thread/thr_init.c | 10 | ||||
-rw-r--r-- | lib/libthr/thread/thr_mutex.c | 7 | ||||
-rw-r--r-- | lib/libthr/thread/thr_printf.c | 1 | ||||
-rw-r--r-- | lib/libthr/thread/thr_private.h | 29 | ||||
-rw-r--r-- | lib/libthr/thread/thr_sig.c | 180 | ||||
-rw-r--r-- | lib/libthr/thread/thr_spec.c | 201 | ||||
-rw-r--r-- | lib/libthr/thread/thr_spinlock.c | 10 | ||||
-rw-r--r-- | lib/libthr/thread/thr_syscalls.c | 558 |
14 files changed, 507 insertions, 567 deletions
diff --git a/lib/libthr/thread/Makefile.inc b/lib/libthr/thread/Makefile.inc index ddde6e9..1a7c63d 100644 --- a/lib/libthr/thread/Makefile.inc +++ b/lib/libthr/thread/Makefile.inc @@ -14,6 +14,7 @@ SRCS+= \ thr_cond.c \ thr_condattr.c \ thr_create.c \ + thr_ctrdtr.c \ thr_detach.c \ thr_equal.c \ thr_event.c \ diff --git a/lib/libthr/thread/thr_barrier.c b/lib/libthr/thread/thr_barrier.c index 86f880e..10b6346 100644 --- a/lib/libthr/thread/thr_barrier.c +++ b/lib/libthr/thread/thr_barrier.c @@ -86,16 +86,13 @@ _pthread_barrier_init(pthread_barrier_t *barrier, if (barrier == NULL || count <= 0) return (EINVAL); - bar = malloc(sizeof(struct pthread_barrier)); + bar = calloc(1, sizeof(struct pthread_barrier)); if (bar == NULL) return (ENOMEM); _thr_umutex_init(&bar->b_lock); _thr_ucond_init(&bar->b_cv); - bar->b_cycle = 0; - bar->b_waiters = 0; bar->b_count = count; - bar->b_refcount = 0; *barrier = bar; return (0); diff --git a/lib/libthr/thread/thr_clean.c b/lib/libthr/thread/thr_clean.c index dc5b0c7..f200726 100644 --- a/lib/libthr/thread/thr_clean.c +++ b/lib/libthr/thread/thr_clean.c @@ -84,7 +84,7 @@ _pthread_cleanup_push(void (*routine) (void *), void *arg) curthread->unwind_disabled = 1; #endif if ((newbuf = (struct pthread_cleanup *) - malloc(sizeof(struct _pthread_cleanup_info))) != NULL) { + malloc(sizeof(struct pthread_cleanup))) != NULL) { newbuf->routine = routine; newbuf->routine_arg = arg; newbuf->onheap = 1; diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c index a41b33f..df3509d 100644 --- a/lib/libthr/thread/thr_create.c +++ b/lib/libthr/thread/thr_create.c @@ -40,6 +40,7 @@ #include <pthread_np.h> #include "un-namespace.h" +#include "libc_private.h" #include "thr_private.h" static int create_stack(struct pthread_attr *pattr); @@ -66,8 +67,11 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, /* * Tell libc and others now they need lock to protect their data. */ - if (_thr_isthreaded() == 0 && _thr_setthreaded(1)) - return (EAGAIN); + if (_thr_isthreaded() == 0) { + _malloc_first_thread(); + if (_thr_setthreaded(1)) + return (EAGAIN); + } curthread = _get_curthread(); if ((new_thread = _thr_alloc(curthread)) == NULL) diff --git a/lib/libthr/thread/thr_ctrdtr.c b/lib/libthr/thread/thr_ctrdtr.c new file mode 100644 index 0000000..9d4301e --- /dev/null +++ b/lib/libthr/thread/thr_ctrdtr.c @@ -0,0 +1,56 @@ +/*- + * Copyright (C) 2003 Jake Burkholder <jake@freebsd.org> + * Copyright (C) 2003 David Xu <davidxu@freebsd.org> + * Copyright (c) 2001,2003 Daniel Eischen <deischen@freebsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Neither the name of the author nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <rtld_tls.h> + +#include "thr_private.h" + +struct tcb * +_tcb_ctor(struct pthread *thread, int initial) +{ + struct tcb *tcb; + + if (initial) + tcb = _tcb_get(); + else + tcb = _rtld_allocate_tls(NULL, sizeof(struct tcb), 16); + if (tcb) + tcb->tcb_thread = thread; + return (tcb); +} + +void +_tcb_dtor(struct tcb *tcb) +{ + + _rtld_free_tls(tcb, sizeof(struct tcb), 16); +} diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c index fc87688..7dc8ca8 100644 --- a/lib/libthr/thread/thr_fork.c +++ b/lib/libthr/thread/thr_fork.c @@ -128,12 +128,10 @@ __pthread_cxa_finalize(struct dl_phdr_info *phdr_info) _thr_sigact_unload(phdr_info); } -__weak_reference(_fork, fork); - -pid_t _fork(void); +__weak_reference(__thr_fork, _fork); pid_t -_fork(void) +__thr_fork(void) { struct pthread *curthread; struct pthread_atfork *af; diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c index 6d6a532..9a1a67a 100644 --- a/lib/libthr/thread/thr_init.c +++ b/lib/libthr/thread/thr_init.c @@ -37,6 +37,7 @@ #include <sys/types.h> #include <sys/signalvar.h> #include <sys/ioctl.h> +#include <sys/link_elf.h> #include <sys/resource.h> #include <sys/sysctl.h> #include <sys/ttycom.h> @@ -302,7 +303,7 @@ _thread_init_hack(void) void _libpthread_init(struct pthread *curthread) { - int fd, first = 0; + int fd, first, dlopened; /* Check if this function has already been called: */ if ((_thr_initial != NULL) && (curthread == NULL)) @@ -316,6 +317,7 @@ _libpthread_init(struct pthread *curthread) if (sizeof(jmp_table) != (sizeof(pthread_func_t) * PJT_MAX * 2)) PANIC("Thread jump table not properly initialized"); memcpy(__thr_jtable, jmp_table, sizeof(jmp_table)); + __thr_interpose_libc(); /* * Check for the special case of this process running as @@ -349,7 +351,10 @@ _libpthread_init(struct pthread *curthread) if (curthread == NULL) PANIC("Can't allocate initial thread"); init_main_thread(curthread); + } else { + first = 0; } + /* * Add the thread to the thread list queue. */ @@ -361,7 +366,8 @@ _libpthread_init(struct pthread *curthread) if (first) { _thr_initial = curthread; - _thr_signal_init(); + dlopened = _rtld_is_dlopened(&_thread_autoinit_dummy_decl) != 0; + _thr_signal_init(dlopened); if (_thread_event_mask & TD_CREATE) _thr_report_creation(curthread, curthread); /* diff --git a/lib/libthr/thread/thr_mutex.c b/lib/libthr/thread/thr_mutex.c index 61ff077..26e8776 100644 --- a/lib/libthr/thread/thr_mutex.c +++ b/lib/libthr/thread/thr_mutex.c @@ -633,7 +633,7 @@ mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer) { struct pthread *curthread = _get_curthread(); uint32_t id; - int defered; + int defered, error; if (__predict_false(m <= THR_MUTEX_DESTROYED)) { if (m == THR_MUTEX_DESTROYED) @@ -647,6 +647,7 @@ mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer) if (__predict_false(m->m_owner != curthread)) return (EPERM); + error = 0; id = TID(curthread); if (__predict_false( PMUTEX_TYPE(m->m_flags) == PTHREAD_MUTEX_RECURSIVE && @@ -660,7 +661,7 @@ mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer) defered = 0; DEQUEUE_MUTEX(curthread, m); - _thr_umutex_unlock2(&m->m_lock, id, mtx_defer); + error = _thr_umutex_unlock2(&m->m_lock, id, mtx_defer); if (mtx_defer == NULL && defered) { _thr_wake_all(curthread->defer_waiters, @@ -670,7 +671,7 @@ mutex_unlock_common(struct pthread_mutex *m, int cv, int *mtx_defer) } if (!cv && m->m_flags & PMUTEX_FLAG_PRIVATE) THR_CRITICAL_LEAVE(curthread); - return (0); + return (error); } int diff --git a/lib/libthr/thread/thr_printf.c b/lib/libthr/thread/thr_printf.c index 7d32ae7..a64b446 100644 --- a/lib/libthr/thread/thr_printf.c +++ b/lib/libthr/thread/thr_printf.c @@ -31,6 +31,7 @@ #include <unistd.h> #include <pthread.h> +#include "libc_private.h" #include "thr_private.h" static void pchar(int fd, char c); diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h index c6651cd..ed24c38 100644 --- a/lib/libthr/thread/thr_private.h +++ b/lib/libthr/thread/thr_private.h @@ -337,7 +337,7 @@ struct pthread_key { /* * lwpid_t is 32bit but kernel thr API exports tid as long type - * in very earily date. + * to preserve the ABI for M:N model in very early date (r131431). */ #define TID(thread) ((uint32_t) ((thread)->tid)) @@ -763,7 +763,7 @@ void _thr_cancel_leave(struct pthread *, int) __hidden; void _thr_testcancel(struct pthread *) __hidden; void _thr_signal_block(struct pthread *) __hidden; void _thr_signal_unblock(struct pthread *) __hidden; -void _thr_signal_init(void) __hidden; +void _thr_signal_init(int) __hidden; void _thr_signal_deinit(void) __hidden; int _thr_send_sig(struct pthread *, int sig) __hidden; void _thr_list_init(void) __hidden; @@ -839,7 +839,6 @@ int __sys_close(int); int __sys_fork(void); pid_t __sys_getpid(void); ssize_t __sys_read(int, void *, size_t); -ssize_t __sys_write(int, const void *, size_t); void __sys_exit(int); #endif @@ -906,12 +905,36 @@ int _sleepq_remove(struct sleepqueue *, struct pthread *) __hidden; void _sleepq_drop(struct sleepqueue *, void (*cb)(struct pthread *, void *arg), void *) __hidden; +int _pthread_mutex_init_calloc_cb(pthread_mutex_t *mutex, + void *(calloc_cb)(size_t, size_t)); + struct dl_phdr_info; void __pthread_cxa_finalize(struct dl_phdr_info *phdr_info); void _thr_tsd_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_sigact_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_stack_fix_protection(struct pthread *thrd); +int *__error_threaded(void) __hidden; +void __thr_interpose_libc(void) __hidden; +pid_t __thr_fork(void); +int __thr_setcontext(const ucontext_t *ucp); +int __thr_sigaction(int sig, const struct sigaction *act, + struct sigaction *oact) __hidden; +int __thr_sigprocmask(int how, const sigset_t *set, sigset_t *oset); +int __thr_sigsuspend(const sigset_t * set); +int __thr_sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec * timeout); +int __thr_sigwait(const sigset_t *set, int *sig); +int __thr_sigwaitinfo(const sigset_t *set, siginfo_t *info); +int __thr_swapcontext(ucontext_t *oucp, const ucontext_t *ucp); + +struct _spinlock; +void __thr_spinunlock(struct _spinlock *lck); +void __thr_spinlock(struct _spinlock *lck); + +struct tcb *_tcb_ctor(struct pthread *, int); +void _tcb_dtor(struct tcb *); + __END_DECLS #endif /* !_THR_PRIVATE_H */ diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c index 57c9406..11a131c 100644 --- a/lib/libthr/thread/thr_sig.c +++ b/lib/libthr/thread/thr_sig.c @@ -38,6 +38,7 @@ #include "un-namespace.h" #include "libc_private.h" +#include "libc_private.h" #include "thr_private.h" /* #define DEBUG_SIGNAL */ @@ -54,24 +55,23 @@ struct usigaction { static struct usigaction _thr_sigact[_SIG_MAXSIG]; +static inline struct usigaction * +__libc_sigaction_slot(int signo) +{ + + return (&_thr_sigact[signo - 1]); +} + static void thr_sighandler(int, siginfo_t *, void *); static void handle_signal(struct sigaction *, int, siginfo_t *, ucontext_t *); static void check_deferred_signal(struct pthread *); static void check_suspend(struct pthread *); static void check_cancel(struct pthread *curthread, ucontext_t *ucp); -int ___pause(void); -int _raise(int); -int __sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec * timeout); int _sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec * timeout); -int __sigwaitinfo(const sigset_t *set, siginfo_t *info); int _sigwaitinfo(const sigset_t *set, siginfo_t *info); -int ___sigwait(const sigset_t *set, int *sig); int _sigwait(const sigset_t *set, int *sig); -int __sigsuspend(const sigset_t *sigmask); -int _sigaction(int, const struct sigaction *, struct sigaction *); int _setcontext(const ucontext_t *); int _swapcontext(ucontext_t *, const ucontext_t *); @@ -143,8 +143,8 @@ sigcancel_handler(int sig __unused, errno = err; } -typedef void (*ohandler)(int sig, int code, - struct sigcontext *scp, char *addr, __sighandler_t *catcher); +typedef void (*ohandler)(int sig, int code, struct sigcontext *scp, + char *addr, __sighandler_t *catcher); /* * The signal handler wrapper is entered with all signal masked. @@ -152,15 +152,19 @@ typedef void (*ohandler)(int sig, int code, static void thr_sighandler(int sig, siginfo_t *info, void *_ucp) { - struct pthread *curthread = _get_curthread(); - ucontext_t *ucp = _ucp; + struct pthread *curthread; + ucontext_t *ucp; struct sigaction act; + struct usigaction *usa; int err; err = errno; - _thr_rwl_rdlock(&_thr_sigact[sig-1].lock); - act = _thr_sigact[sig-1].sigact; - _thr_rwl_unlock(&_thr_sigact[sig-1].lock); + curthread = _get_curthread(); + ucp = _ucp; + usa = __libc_sigaction_slot(sig); + _thr_rwl_rdlock(&usa->lock); + act = usa->sigact; + _thr_rwl_unlock(&usa->lock); errno = err; curthread->deferred_run = 0; @@ -234,12 +238,12 @@ handle_signal(struct sigaction *actp, int sig, siginfo_t *info, ucontext_t *ucp) * so after setjmps() returns once more, the user code may need to * re-set cancel_enable flag by calling pthread_setcancelstate(). */ - if ((actp->sa_flags & SA_SIGINFO) != 0) - (*(sigfunc))(sig, info, ucp); - else { - ((ohandler)(*sigfunc))( - sig, info->si_code, (struct sigcontext *)ucp, - info->si_addr, (__sighandler_t *)sigfunc); + if ((actp->sa_flags & SA_SIGINFO) != 0) { + sigfunc(sig, info, ucp); + } else { + ((ohandler)sigfunc)(sig, info->si_code, + (struct sigcontext *)ucp, info->si_addr, + (__sighandler_t *)sigfunc); } err = errno; @@ -395,9 +399,34 @@ check_suspend(struct pthread *curthread) } void -_thr_signal_init(void) +_thr_signal_init(int dlopened) { - struct sigaction act; + struct sigaction act, nact, oact; + struct usigaction *usa; + sigset_t oldset; + int sig, error; + + if (dlopened) { + __sys_sigprocmask(SIG_SETMASK, &_thr_maskset, &oldset); + for (sig = 1; sig <= _SIG_MAXSIG; sig++) { + if (sig == SIGCANCEL) + continue; + error = __sys_sigaction(sig, NULL, &oact); + if (error == -1 || oact.sa_handler == SIG_DFL || + oact.sa_handler == SIG_IGN) + continue; + usa = __libc_sigaction_slot(sig); + usa->sigact = oact; + nact = oact; + remove_thr_signals(&usa->sigact.sa_mask); + nact.sa_flags &= ~SA_NODEFER; + nact.sa_flags |= SA_SIGINFO; + nact.sa_sigaction = thr_sighandler; + nact.sa_mask = _thr_maskset; + (void)__sys_sigaction(sig, &nact, NULL); + } + __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); + } /* Install SIGCANCEL handler. */ SIGFILLSET(act.sa_mask); @@ -418,18 +447,20 @@ _thr_sigact_unload(struct dl_phdr_info *phdr_info) struct pthread *curthread = _get_curthread(); struct urwlock *rwlp; struct sigaction *actp; + struct usigaction *usa; struct sigaction kact; void (*handler)(int); int sig; _thr_signal_block(curthread); for (sig = 1; sig <= _SIG_MAXSIG; sig++) { - actp = &_thr_sigact[sig-1].sigact; + usa = __libc_sigaction_slot(sig); + actp = &usa->sigact; retry: handler = actp->sa_handler; if (handler != SIG_DFL && handler != SIG_IGN && __elf_phdr_match_addr(phdr_info, handler)) { - rwlp = &_thr_sigact[sig-1].lock; + rwlp = &usa->lock; _thr_rwl_wrlock(rwlp); if (handler != actp->sa_handler) { _thr_rwl_unlock(rwlp); @@ -455,7 +486,7 @@ _thr_signal_prefork(void) int i; for (i = 1; i <= _SIG_MAXSIG; ++i) - _thr_rwl_rdlock(&_thr_sigact[i-1].lock); + _thr_rwl_rdlock(&__libc_sigaction_slot(i)->lock); } void @@ -464,7 +495,7 @@ _thr_signal_postfork(void) int i; for (i = 1; i <= _SIG_MAXSIG; ++i) - _thr_rwl_unlock(&_thr_sigact[i-1].lock); + _thr_rwl_unlock(&__libc_sigaction_slot(i)->lock); } void @@ -472,8 +503,10 @@ _thr_signal_postfork_child(void) { int i; - for (i = 1; i <= _SIG_MAXSIG; ++i) - bzero(&_thr_sigact[i-1].lock, sizeof(struct urwlock)); + for (i = 1; i <= _SIG_MAXSIG; ++i) { + bzero(&__libc_sigaction_slot(i) -> lock, + sizeof(struct urwlock)); + } } void @@ -481,84 +514,64 @@ _thr_signal_deinit(void) { } -__weak_reference(___pause, pause); - -int -___pause(void) -{ - sigset_t oset; - - if (_sigprocmask(SIG_BLOCK, NULL, &oset) == -1) - return (-1); - return (__sigsuspend(&oset)); -} - -__weak_reference(_raise, raise); - -int -_raise(int sig) -{ - return _thr_send_sig(_get_curthread(), sig); -} - -__weak_reference(_sigaction, sigaction); - int -_sigaction(int sig, const struct sigaction * act, struct sigaction * oact) +__thr_sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { struct sigaction newact, oldact, oldact2; sigset_t oldset; - int ret = 0, err = 0; + struct usigaction *usa; + int ret, err; if (!_SIG_VALID(sig) || sig == SIGCANCEL) { errno = EINVAL; return (-1); } - if (act) - newact = *act; + ret = 0; + err = 0; + usa = __libc_sigaction_slot(sig); __sys_sigprocmask(SIG_SETMASK, &_thr_maskset, &oldset); - _thr_rwl_wrlock(&_thr_sigact[sig-1].lock); + _thr_rwl_wrlock(&usa->lock); if (act != NULL) { - oldact2 = _thr_sigact[sig-1].sigact; + oldact2 = usa->sigact; + newact = *act; /* * if a new sig handler is SIG_DFL or SIG_IGN, - * don't remove old handler from _thr_sigact[], + * don't remove old handler from __libc_sigact[], * so deferred signals still can use the handlers, * multiple threads invoking sigaction itself is * a race condition, so it is not a problem. */ if (newact.sa_handler != SIG_DFL && newact.sa_handler != SIG_IGN) { - _thr_sigact[sig-1].sigact = newact; - remove_thr_signals( - &_thr_sigact[sig-1].sigact.sa_mask); + usa->sigact = newact; + remove_thr_signals(&usa->sigact.sa_mask); newact.sa_flags &= ~SA_NODEFER; newact.sa_flags |= SA_SIGINFO; newact.sa_sigaction = thr_sighandler; newact.sa_mask = _thr_maskset; /* mask all signals */ } - if ((ret = __sys_sigaction(sig, &newact, &oldact))) { + ret = __sys_sigaction(sig, &newact, &oldact); + if (ret == -1) { err = errno; - _thr_sigact[sig-1].sigact = oldact2; + usa->sigact = oldact2; } } else if (oact != NULL) { ret = __sys_sigaction(sig, NULL, &oldact); err = errno; } - if (oldact.sa_handler != SIG_DFL && - oldact.sa_handler != SIG_IGN) { + if (oldact.sa_handler != SIG_DFL && oldact.sa_handler != SIG_IGN) { if (act != NULL) oldact = oldact2; else if (oact != NULL) - oldact = _thr_sigact[sig-1].sigact; + oldact = usa->sigact; } - _thr_rwl_unlock(&_thr_sigact[sig-1].lock); + _thr_rwl_unlock(&usa->lock); __sys_sigprocmask(SIG_SETMASK, &oldset, NULL); if (ret == 0) { @@ -570,10 +583,8 @@ _sigaction(int sig, const struct sigaction * act, struct sigaction * oact) return (ret); } -__weak_reference(_sigprocmask, sigprocmask); - int -_sigprocmask(int how, const sigset_t *set, sigset_t *oset) +__thr_sigprocmask(int how, const sigset_t *set, sigset_t *oset) { const sigset_t *p = set; sigset_t newset; @@ -593,13 +604,12 @@ __weak_reference(_pthread_sigmask, pthread_sigmask); int _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) { - if (_sigprocmask(how, set, oset)) + + if (__thr_sigprocmask(how, set, oset)) return (errno); return (0); } -__weak_reference(__sigsuspend, sigsuspend); - int _sigsuspend(const sigset_t * set) { @@ -609,7 +619,7 @@ _sigsuspend(const sigset_t * set) } int -__sigsuspend(const sigset_t * set) +__thr_sigsuspend(const sigset_t * set) { struct pthread *curthread; sigset_t newset; @@ -633,10 +643,6 @@ __sigsuspend(const sigset_t * set) return (ret); } -__weak_reference(___sigwait, sigwait); -__weak_reference(__sigtimedwait, sigtimedwait); -__weak_reference(__sigwaitinfo, sigwaitinfo); - int _sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec * timeout) @@ -653,8 +659,8 @@ _sigtimedwait(const sigset_t *set, siginfo_t *info, * it is not canceled. */ int -__sigtimedwait(const sigset_t *set, siginfo_t *info, - const struct timespec * timeout) +__thr_sigtimedwait(const sigset_t *set, siginfo_t *info, + const struct timespec * timeout) { struct pthread *curthread = _get_curthread(); sigset_t newset; @@ -681,7 +687,7 @@ _sigwaitinfo(const sigset_t *set, siginfo_t *info) * it is not canceled. */ int -__sigwaitinfo(const sigset_t *set, siginfo_t *info) +__thr_sigwaitinfo(const sigset_t *set, siginfo_t *info) { struct pthread *curthread = _get_curthread(); sigset_t newset; @@ -707,7 +713,7 @@ _sigwait(const sigset_t *set, int *sig) * it is not canceled. */ int -___sigwait(const sigset_t *set, int *sig) +__thr_sigwait(const sigset_t *set, int *sig) { struct pthread *curthread = _get_curthread(); sigset_t newset; @@ -721,9 +727,8 @@ ___sigwait(const sigset_t *set, int *sig) return (ret); } -__weak_reference(_setcontext, setcontext); int -_setcontext(const ucontext_t *ucp) +__thr_setcontext(const ucontext_t *ucp) { ucontext_t uc; @@ -735,12 +740,11 @@ _setcontext(const ucontext_t *ucp) return __sys_setcontext(ucp); (void) memcpy(&uc, ucp, sizeof(uc)); SIGDELSET(uc.uc_sigmask, SIGCANCEL); - return __sys_setcontext(&uc); + return (__sys_setcontext(&uc)); } -__weak_reference(_swapcontext, swapcontext); int -_swapcontext(ucontext_t *oucp, const ucontext_t *ucp) +__thr_swapcontext(ucontext_t *oucp, const ucontext_t *ucp) { ucontext_t uc; @@ -753,5 +757,5 @@ _swapcontext(ucontext_t *oucp, const ucontext_t *ucp) SIGDELSET(uc.uc_sigmask, SIGCANCEL); ucp = &uc; } - return __sys_swapcontext(oucp, ucp); + return (__sys_swapcontext(oucp, ucp)); } diff --git a/lib/libthr/thread/thr_spec.c b/lib/libthr/thread/thr_spec.c index 46a6105..b53c4b7 100644 --- a/lib/libthr/thread/thr_spec.c +++ b/lib/libthr/thread/thr_spec.c @@ -30,6 +30,7 @@ */ #include "namespace.h" +#include <sys/mman.h> #include <signal.h> #include <stdlib.h> #include <string.h> @@ -40,7 +41,6 @@ #include "thr_private.h" -/* Static variables: */ struct pthread_key _thread_keytable[PTHREAD_KEYS_MAX]; __weak_reference(_pthread_key_create, pthread_key_create); @@ -50,7 +50,7 @@ __weak_reference(_pthread_setspecific, pthread_setspecific); int -_pthread_key_create(pthread_key_t *key, void (*destructor) (void *)) +_pthread_key_create(pthread_key_t *key, void (*destructor)(void *)) { struct pthread *curthread; int i; @@ -59,7 +59,6 @@ _pthread_key_create(pthread_key_t *key, void (*destructor) (void *)) curthread = _get_curthread(); - /* Lock the key table: */ THR_LOCK_ACQUIRE(curthread, &_keytable_lock); for (i = 0; i < PTHREAD_KEYS_MAX; i++) { @@ -68,14 +67,12 @@ _pthread_key_create(pthread_key_t *key, void (*destructor) (void *)) _thread_keytable[i].destructor = destructor; _thread_keytable[i].seqno++; - /* Unlock the key table: */ THR_LOCK_RELEASE(curthread, &_keytable_lock); *key = i + 1; return (0); } } - /* Unlock the key table: */ THR_LOCK_RELEASE(curthread, &_keytable_lock); return (EAGAIN); } @@ -83,44 +80,40 @@ _pthread_key_create(pthread_key_t *key, void (*destructor) (void *)) int _pthread_key_delete(pthread_key_t userkey) { - struct pthread *curthread = _get_curthread(); - int key = userkey - 1; - int ret = 0; - - if ((unsigned int)key < PTHREAD_KEYS_MAX) { - /* Lock the key table: */ - THR_LOCK_ACQUIRE(curthread, &_keytable_lock); - - if (_thread_keytable[key].allocated) - _thread_keytable[key].allocated = 0; - else - ret = EINVAL; + struct pthread *curthread; + int key, ret; - /* Unlock the key table: */ - THR_LOCK_RELEASE(curthread, &_keytable_lock); - } else + key = userkey - 1; + if ((unsigned int)key >= PTHREAD_KEYS_MAX) + return (EINVAL); + curthread = _get_curthread(); + THR_LOCK_ACQUIRE(curthread, &_keytable_lock); + if (_thread_keytable[key].allocated) { + _thread_keytable[key].allocated = 0; + ret = 0; + } else { ret = EINVAL; + } + THR_LOCK_RELEASE(curthread, &_keytable_lock); return (ret); } void _thread_cleanupspecific(void) { - struct pthread *curthread = _get_curthread(); - void (*destructor)( void *); - const void *data = NULL; - int key; - int i; + struct pthread *curthread; + void (*destructor)(void *); + const void *data; + int i, key; + curthread = _get_curthread(); if (curthread->specific == NULL) return; - - /* Lock the key table: */ THR_LOCK_ACQUIRE(curthread, &_keytable_lock); - for (i = 0; (i < PTHREAD_DESTRUCTOR_ITERATIONS) && - (curthread->specific_data_count > 0); i++) { - for (key = 0; (key < PTHREAD_KEYS_MAX) && - (curthread->specific_data_count > 0); key++) { + for (i = 0; i < PTHREAD_DESTRUCTOR_ITERATIONS && + curthread->specific_data_count > 0; i++) { + for (key = 0; key < PTHREAD_KEYS_MAX && + curthread->specific_data_count > 0; key++) { destructor = NULL; if (_thread_keytable[key].allocated && @@ -128,31 +121,29 @@ _thread_cleanupspecific(void) if (curthread->specific[key].seqno == _thread_keytable[key].seqno) { data = curthread->specific[key].data; - destructor = _thread_keytable[key].destructor; + destructor = _thread_keytable[key]. + destructor; } curthread->specific[key].data = NULL; curthread->specific_data_count--; - } - else if (curthread->specific[key].data != NULL) { + } else if (curthread->specific[key].data != NULL) { /* - * This can happen if the key is deleted via - * pthread_key_delete without first setting the value - * to NULL in all threads. POSIX says that the - * destructor is not invoked in this case. + * This can happen if the key is + * deleted via pthread_key_delete + * without first setting the value to + * NULL in all threads. POSIX says + * that the destructor is not invoked + * in this case. */ curthread->specific[key].data = NULL; curthread->specific_data_count--; } /* - * If there is a destructor, call it - * with the key table entry unlocked: + * If there is a destructor, call it with the + * key table entry unlocked. */ if (destructor != NULL) { - /* - * Don't hold the lock while calling the - * destructor: - */ THR_LOCK_RELEASE(curthread, &_keytable_lock); destructor(__DECONST(void *, data)); THR_LOCK_ACQUIRE(curthread, &_keytable_lock); @@ -160,102 +151,92 @@ _thread_cleanupspecific(void) } } THR_LOCK_RELEASE(curthread, &_keytable_lock); - free(curthread->specific); + munmap(curthread->specific, PTHREAD_KEYS_MAX * sizeof(struct + pthread_specific_elem)); curthread->specific = NULL; - if (curthread->specific_data_count > 0) + if (curthread->specific_data_count > 0) { stderr_debug("Thread %p has exited with leftover " "thread-specific data after %d destructor iterations\n", curthread, PTHREAD_DESTRUCTOR_ITERATIONS); -} - -static inline struct pthread_specific_elem * -pthread_key_allocate_data(void) -{ - struct pthread_specific_elem *new_data; - - new_data = (struct pthread_specific_elem *) - calloc(1, sizeof(struct pthread_specific_elem) * PTHREAD_KEYS_MAX); - return (new_data); + } } int _pthread_setspecific(pthread_key_t userkey, const void *value) { - struct pthread *pthread; - pthread_key_t key = userkey - 1; - int ret = 0; + struct pthread *pthread; + void *tmp; + pthread_key_t key; - /* Point to the running thread: */ - pthread = _get_curthread(); + key = userkey - 1; + if ((unsigned int)key >= PTHREAD_KEYS_MAX || + !_thread_keytable[key].allocated) + return (EINVAL); - if ((pthread->specific) || - (pthread->specific = pthread_key_allocate_data())) { - if ((unsigned int)key < PTHREAD_KEYS_MAX) { - if (_thread_keytable[key].allocated) { - if (pthread->specific[key].data == NULL) { - if (value != NULL) - pthread->specific_data_count++; - } else if (value == NULL) - pthread->specific_data_count--; - pthread->specific[key].data = value; - pthread->specific[key].seqno = - _thread_keytable[key].seqno; - ret = 0; - } else - ret = EINVAL; - } else - ret = EINVAL; - } else - ret = ENOMEM; - return (ret); + pthread = _get_curthread(); + if (pthread->specific == NULL) { + tmp = mmap(NULL, PTHREAD_KEYS_MAX * + sizeof(struct pthread_specific_elem), + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0); + if (tmp == MAP_FAILED) + return (ENOMEM); + pthread->specific = tmp; + } + if (pthread->specific[key].data == NULL) { + if (value != NULL) + pthread->specific_data_count++; + } else if (value == NULL) + pthread->specific_data_count--; + pthread->specific[key].data = value; + pthread->specific[key].seqno = _thread_keytable[key].seqno; + return (0); } void * _pthread_getspecific(pthread_key_t userkey) { - struct pthread *pthread; - pthread_key_t key = userkey - 1; - const void *data; + struct pthread *pthread; + const void *data; + pthread_key_t key; - /* Point to the running thread: */ - pthread = _get_curthread(); + /* Check if there is specific data. */ + key = userkey - 1; + if ((unsigned int)key >= PTHREAD_KEYS_MAX) + return (NULL); - /* Check if there is specific data: */ - if (pthread->specific != NULL && (unsigned int)key < PTHREAD_KEYS_MAX) { - /* Check if this key has been used before: */ - if (_thread_keytable[key].allocated && - (pthread->specific[key].seqno == _thread_keytable[key].seqno)) { - /* Return the value: */ - data = pthread->specific[key].data; - } else { - /* - * This key has not been used before, so return NULL - * instead: - */ - data = NULL; - } - } else - /* No specific data has been created, so just return NULL: */ + pthread = _get_curthread(); + /* Check if this key has been used before. */ + if (_thread_keytable[key].allocated && pthread->specific != NULL && + pthread->specific[key].seqno == _thread_keytable[key].seqno) { + /* Return the value: */ + data = pthread->specific[key].data; + } else { + /* + * This key has not been used before, so return NULL + * instead. + */ data = NULL; + } return (__DECONST(void *, data)); } void _thr_tsd_unload(struct dl_phdr_info *phdr_info) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; void (*destructor)(void *); int key; + curthread = _get_curthread(); THR_LOCK_ACQUIRE(curthread, &_keytable_lock); for (key = 0; key < PTHREAD_KEYS_MAX; key++) { - if (_thread_keytable[key].allocated) { - destructor = _thread_keytable[key].destructor; - if (destructor != NULL) { - if (__elf_phdr_match_addr(phdr_info, destructor)) - _thread_keytable[key].destructor = NULL; - } - } + if (!_thread_keytable[key].allocated) + continue; + destructor = _thread_keytable[key].destructor; + if (destructor == NULL) + continue; + if (__elf_phdr_match_addr(phdr_info, destructor)) + _thread_keytable[key].destructor = NULL; } THR_LOCK_RELEASE(curthread, &_keytable_lock); } diff --git a/lib/libthr/thread/thr_spinlock.c b/lib/libthr/thread/thr_spinlock.c index ecc8067..380d10d 100644 --- a/lib/libthr/thread/thr_spinlock.c +++ b/lib/libthr/thread/thr_spinlock.c @@ -61,7 +61,7 @@ static void init_spinlock(spinlock_t *lck); */ void -_spinunlock(spinlock_t *lck) +__thr_spinunlock(spinlock_t *lck) { struct spinlock_extra *_extra; @@ -70,7 +70,7 @@ _spinunlock(spinlock_t *lck) } void -_spinlock(spinlock_t *lck) +__thr_spinlock(spinlock_t *lck) { struct spinlock_extra *_extra; @@ -84,12 +84,6 @@ _spinlock(spinlock_t *lck) THR_UMUTEX_LOCK(_get_curthread(), &_extra->lock); } -void -_spinlock_debug(spinlock_t *lck, char *fname __unused, int lineno __unused) -{ - _spinlock(lck); -} - static void init_spinlock(spinlock_t *lck) { diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c index 7a08302..7c05697 100644 --- a/lib/libthr/thread/thr_syscalls.c +++ b/lib/libthr/thread/thr_syscalls.c @@ -1,9 +1,13 @@ /* + * Copyright (c) 2014 The FreeBSD Foundation. * Copyright (C) 2005 David Xu <davidxu@freebsd.org>. * Copyright (c) 2003 Daniel Eischen <deischen@freebsd.org>. * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>. * All rights reserved. * + * Portions of this software were developed by Konstantin Belousov + * under sponsorship from the FreeBSD Foundation. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -27,8 +31,6 @@ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD$ */ /* @@ -61,6 +63,9 @@ * */ +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + #include "namespace.h" #include <sys/types.h> #include <sys/mman.h> @@ -87,85 +92,11 @@ #include <pthread.h> #include "un-namespace.h" +#include "libc_private.h" #include "thr_private.h" -extern int __creat(const char *, mode_t); -extern int __pselect(int, fd_set *, fd_set *, fd_set *, - const struct timespec *, const sigset_t *); -extern unsigned __sleep(unsigned int); -extern int __system(const char *); -extern int __tcdrain(int); -extern int __usleep(useconds_t); -extern pid_t __wait(int *); -extern pid_t __waitpid(pid_t, int *, int); -extern int __sys_aio_suspend(const struct aiocb * const[], int, - const struct timespec *); -extern int __sys_accept(int, struct sockaddr *, socklen_t *); -extern int __sys_accept4(int, struct sockaddr *, socklen_t *, int); -extern int __sys_connect(int, const struct sockaddr *, socklen_t); -extern int __sys_fsync(int); -extern int __sys_msync(void *, size_t, int); -extern int __sys_pselect(int, fd_set *, fd_set *, fd_set *, - const struct timespec *, const sigset_t *); -extern int __sys_poll(struct pollfd *, unsigned, int); -extern ssize_t __sys_recv(int, void *, size_t, int); -extern ssize_t __sys_recvfrom(int, void *, size_t, int, struct sockaddr *, socklen_t *); -extern ssize_t __sys_recvmsg(int, struct msghdr *, int); -extern int __sys_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); -extern int __sys_sendfile(int, int, off_t, size_t, struct sf_hdtr *, - off_t *, int); -extern ssize_t __sys_sendmsg(int, const struct msghdr *, int); -extern ssize_t __sys_sendto(int, const void *,size_t, int, const struct sockaddr *, socklen_t); -extern ssize_t __sys_readv(int, const struct iovec *, int); -extern pid_t __sys_wait4(pid_t, int *, int, struct rusage *); -extern ssize_t __sys_writev(int, const struct iovec *, int); - -int ___creat(const char *, mode_t); -int ___pselect(int, fd_set *, fd_set *, fd_set *, - const struct timespec *, const sigset_t *); -unsigned ___sleep(unsigned); -int ___system(const char *); -int ___tcdrain(int); -int ___usleep(useconds_t useconds); -pid_t ___wait(int *); -pid_t ___waitpid(pid_t, int *, int); -int __accept(int, struct sockaddr *, socklen_t *); -int __accept4(int, struct sockaddr *, socklen_t *, int); -int __aio_suspend(const struct aiocb * const iocbs[], int, - const struct timespec *); -int __close(int); -int __connect(int, const struct sockaddr *, socklen_t); -int __fcntl(int, int,...); -#ifdef SYSCALL_COMPAT -extern int __fcntl_compat(int, int,...); -#endif -int __fsync(int); -int __msync(void *, size_t, int); -int __nanosleep(const struct timespec *, struct timespec *); -int __open(const char *, int,...); -int __openat(int, const char *, int,...); -int __poll(struct pollfd *, unsigned int, int); -ssize_t __read(int, void *buf, size_t); -ssize_t __readv(int, const struct iovec *, int); -ssize_t __recvfrom(int, void *, size_t, int f, struct sockaddr *, socklen_t *); -ssize_t __recvmsg(int, struct msghdr *, int); -int __select(int, fd_set *, fd_set *, fd_set *, struct timeval *); -ssize_t __sendmsg(int, const struct msghdr *, int); -ssize_t __sendto(int, const void *, size_t, int, - const struct sockaddr *, socklen_t); -pid_t __wait3(int *, int, struct rusage *); -pid_t __wait4(pid_t, int *, int, struct rusage *); -ssize_t __write(int, const void *, size_t); -ssize_t __writev(int, const struct iovec *, int); - -__weak_reference(__accept, accept); - -/* - * Cancellation behavior: - * If thread is canceled, no socket is created. - */ -int -__accept(int s, struct sockaddr *addr, socklen_t *addrlen) +static int +__thr_accept(int s, struct sockaddr *addr, socklen_t *addrlen) { struct pthread *curthread; int ret; @@ -178,14 +109,12 @@ __accept(int s, struct sockaddr *addr, socklen_t *addrlen) return (ret); } -__weak_reference(__accept4, accept4); - /* * Cancellation behavior: * If thread is canceled, no socket is created. */ -int -__accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) +static int +__thr_accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) { struct pthread *curthread; int ret; @@ -198,15 +127,14 @@ __accept4(int s, struct sockaddr *addr, socklen_t *addrlen, int flags) return (ret); } -__weak_reference(__aio_suspend, aio_suspend); - -int -__aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct +static int +__thr_aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct timespec *timeout) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; int ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_aio_suspend(iocbs, niocb, timeout); _thr_cancel_leave(curthread, 1); @@ -214,8 +142,6 @@ __aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct return (ret); } -__weak_reference(__close, close); - /* * Cancellation behavior: * According to manual of close(), the file descriptor is always deleted. @@ -223,12 +149,13 @@ __weak_reference(__close, close); * descriptor is always deleted despite whether the thread is canceled * or not. */ -int -__close(int fd) +static int +__thr_close(int fd) { - struct pthread *curthread = _get_curthread(); - int ret; + struct pthread *curthread; + int ret; + curthread = _get_curthread(); _thr_cancel_enter2(curthread, 0); ret = __sys_close(fd); _thr_cancel_leave(curthread, 1); @@ -236,18 +163,17 @@ __close(int fd) return (ret); } -__weak_reference(__connect, connect); - /* * Cancellation behavior: * If the thread is canceled, connection is not made. */ -int -__connect(int fd, const struct sockaddr *name, socklen_t namelen) +static int +__thr_connect(int fd, const struct sockaddr *name, socklen_t namelen) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; int ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_connect(fd, name, namelen); _thr_cancel_leave(curthread, ret == -1); @@ -255,27 +181,6 @@ __connect(int fd, const struct sockaddr *name, socklen_t namelen) return (ret); } -__weak_reference(___creat, creat); - -/* - * Cancellation behavior: - * If thread is canceled, file is not created. - */ -int -___creat(const char *path, mode_t mode) -{ - struct pthread *curthread = _get_curthread(); - int ret; - - _thr_cancel_enter(curthread); - ret = __creat(path, mode); - _thr_cancel_leave(curthread, ret == -1); - - return ret; -} - -__weak_reference(__fcntl, fcntl); - /* * Cancellation behavior: * According to specification, only F_SETLKW is a cancellation point. @@ -283,46 +188,38 @@ __weak_reference(__fcntl, fcntl); * is failure, this means the function does not generate side effect * if it is canceled. */ -int -__fcntl(int fd, int cmd,...) +static int +__thr_fcntl(int fd, int cmd, ...) { - struct pthread *curthread = _get_curthread(); - int ret; + struct pthread *curthread; + int ret; va_list ap; + curthread = _get_curthread(); va_start(ap, cmd); if (cmd == F_OSETLKW || cmd == F_SETLKW) { _thr_cancel_enter(curthread); -#ifdef SYSCALL_COMPAT - ret = __fcntl_compat(fd, cmd, va_arg(ap, void *)); -#else ret = __sys_fcntl(fd, cmd, va_arg(ap, void *)); -#endif _thr_cancel_leave(curthread, ret == -1); } else { -#ifdef SYSCALL_COMPAT - ret = __fcntl_compat(fd, cmd, va_arg(ap, void *)); -#else ret = __sys_fcntl(fd, cmd, va_arg(ap, void *)); -#endif } va_end(ap); return (ret); } -__weak_reference(__fsync, fsync); - /* * Cancellation behavior: * Thread may be canceled after system call. */ -int -__fsync(int fd) +static int +__thr_fsync(int fd) { - struct pthread *curthread = _get_curthread(); - int ret; + struct pthread *curthread; + int ret; + curthread = _get_curthread(); _thr_cancel_enter2(curthread, 0); ret = __sys_fsync(fd); _thr_cancel_leave(curthread, 1); @@ -330,34 +227,32 @@ __fsync(int fd) return (ret); } -__weak_reference(__msync, msync); - /* * Cancellation behavior: * Thread may be canceled after system call. */ -int -__msync(void *addr, size_t len, int flags) +static int +__thr_msync(void *addr, size_t len, int flags) { - struct pthread *curthread = _get_curthread(); - int ret; + struct pthread *curthread; + int ret; + curthread = _get_curthread(); _thr_cancel_enter2(curthread, 0); ret = __sys_msync(addr, len, flags); _thr_cancel_leave(curthread, 1); - return ret; + return (ret); } -__weak_reference(__nanosleep, nanosleep); - -int -__nanosleep(const struct timespec *time_to_sleep, +static int +__thr_nanosleep(const struct timespec *time_to_sleep, struct timespec *time_remaining) { - struct pthread *curthread = _get_curthread(); - int ret; + struct pthread *curthread; + int ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_nanosleep(time_to_sleep, time_remaining); _thr_cancel_leave(curthread, 1); @@ -365,99 +260,88 @@ __nanosleep(const struct timespec *time_to_sleep, return (ret); } -__weak_reference(__open, open); - /* * Cancellation behavior: * If the thread is canceled, file is not opened. */ -int -__open(const char *path, int flags,...) +static int +__thr_openat(int fd, const char *path, int flags, ...) { - struct pthread *curthread = _get_curthread(); - int ret; - int mode = 0; + struct pthread *curthread; + int mode, ret; va_list ap; + /* Check if the file is being created: */ - if (flags & O_CREAT) { + if ((flags & O_CREAT) != 0) { /* Get the creation mode: */ va_start(ap, flags); mode = va_arg(ap, int); va_end(ap); + } else { + mode = 0; } + curthread = _get_curthread(); _thr_cancel_enter(curthread); - ret = __sys_open(path, flags, mode); + ret = __sys_openat(fd, path, flags, mode); _thr_cancel_leave(curthread, ret == -1); - return ret; + return (ret); } -__weak_reference(__openat, openat); - /* * Cancellation behavior: - * If the thread is canceled, file is not opened. + * Thread may be canceled at start, but if the system call returns something, + * the thread is not canceled. */ -int -__openat(int fd, const char *path, int flags, ...) +static int +__thr_poll(struct pollfd *fds, unsigned int nfds, int timeout) { - struct pthread *curthread = _get_curthread(); - int ret; - int mode = 0; - va_list ap; + struct pthread *curthread; + int ret; - - /* Check if the file is being created: */ - if (flags & O_CREAT) { - /* Get the creation mode: */ - va_start(ap, flags); - mode = va_arg(ap, int); - va_end(ap); - } - + curthread = _get_curthread(); _thr_cancel_enter(curthread); - ret = __sys_openat(fd, path, flags, mode); + ret = __sys_poll(fds, nfds, timeout); _thr_cancel_leave(curthread, ret == -1); - return ret; + return (ret); } -__weak_reference(__poll, poll); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call returns something, * the thread is not canceled. */ -int -__poll(struct pollfd *fds, unsigned int nfds, int timeout) +static int +__thr_ppoll(struct pollfd pfd[], nfds_t nfds, const struct timespec * + timeout, const sigset_t *newsigmask) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; int ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); - ret = __sys_poll(fds, nfds, timeout); + ret = __sys_ppoll(pfd, nfds, timeout, newsigmask); _thr_cancel_leave(curthread, ret == -1); - return ret; + return (ret); } -__weak_reference(___pselect, pselect); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call returns something, * the thread is not canceled. */ -int -___pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, +static int +__thr_pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, const struct timespec *timo, const sigset_t *mask) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; int ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_pselect(count, rfds, wfds, efds, timo, mask); _thr_cancel_leave(curthread, ret == -1); @@ -465,321 +349,311 @@ ___pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds, return (ret); } -__weak_reference(__read, read); +static int +__thr_kevent(int kq, const struct kevent *changelist, int nchanges, + struct kevent *eventlist, int nevents, const struct timespec *timeout) +{ + struct pthread *curthread; + int ret; + + if (nevents == 0) { + /* + * No blocking, do not make the call cancellable. + */ + return (__sys_kevent(kq, changelist, nchanges, eventlist, + nevents, timeout)); + } + curthread = _get_curthread(); + _thr_cancel_enter(curthread); + ret = __sys_kevent(kq, changelist, nchanges, eventlist, nevents, + timeout); + _thr_cancel_leave(curthread, ret == -1 && nchanges == 0); + + return (ret); +} /* * Cancellation behavior: * Thread may be canceled at start, but if the system call got some data, * the thread is not canceled. */ -ssize_t -__read(int fd, void *buf, size_t nbytes) +static ssize_t +__thr_read(int fd, void *buf, size_t nbytes) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; ssize_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_read(fd, buf, nbytes); _thr_cancel_leave(curthread, ret == -1); - return ret; + return (ret); } -__weak_reference(__readv, readv); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call got some data, * the thread is not canceled. */ -ssize_t -__readv(int fd, const struct iovec *iov, int iovcnt) +static ssize_t +__thr_readv(int fd, const struct iovec *iov, int iovcnt) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; ssize_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_readv(fd, iov, iovcnt); _thr_cancel_leave(curthread, ret == -1); - return ret; + return (ret); } -__weak_reference(__recvfrom, recvfrom); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call got some data, * the thread is not canceled. */ -ssize_t -__recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from, +static ssize_t +__thr_recvfrom(int s, void *b, size_t l, int f, struct sockaddr *from, socklen_t *fl) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; ssize_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_recvfrom(s, b, l, f, from, fl); _thr_cancel_leave(curthread, ret == -1); return (ret); } -__weak_reference(__recvmsg, recvmsg); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call got some data, * the thread is not canceled. */ -ssize_t -__recvmsg(int s, struct msghdr *m, int f) +static ssize_t +__thr_recvmsg(int s, struct msghdr *m, int f) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; ssize_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_recvmsg(s, m, f); _thr_cancel_leave(curthread, ret == -1); return (ret); } -__weak_reference(__select, select); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call returns something, * the thread is not canceled. */ -int -__select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, +static int +__thr_select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; int ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout); _thr_cancel_leave(curthread, ret == -1); - return ret; + return (ret); } -__weak_reference(__sendmsg, sendmsg); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call sent * data, the thread is not canceled. */ -ssize_t -__sendmsg(int s, const struct msghdr *m, int f) +static ssize_t +__thr_sendmsg(int s, const struct msghdr *m, int f) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; ssize_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_sendmsg(s, m, f); _thr_cancel_leave(curthread, ret <= 0); return (ret); } -__weak_reference(__sendto, sendto); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call sent some * data, the thread is not canceled. */ -ssize_t -__sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t, +static ssize_t +__thr_sendto(int s, const void *m, size_t l, int f, const struct sockaddr *t, socklen_t tl) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; ssize_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_sendto(s, m, l, f, t, tl); _thr_cancel_leave(curthread, ret <= 0); return (ret); } -__weak_reference(___sleep, sleep); - -unsigned int -___sleep(unsigned int seconds) +static int +__thr_system(const char *string) { - struct pthread *curthread = _get_curthread(); - unsigned int ret; + struct pthread *curthread; + int ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); - ret = __sleep(seconds); + ret = __libc_system(string); _thr_cancel_leave(curthread, 1); - return (ret); } -__weak_reference(___system, system); - -int -___system(const char *string) -{ - struct pthread *curthread = _get_curthread(); - int ret; - - _thr_cancel_enter(curthread); - ret = __system(string); - _thr_cancel_leave(curthread, 1); - - return ret; -} - -__weak_reference(___tcdrain, tcdrain); - /* * Cancellation behavior: * If thread is canceled, the system call is not completed, * this means not all bytes were drained. */ -int -___tcdrain(int fd) +static int +__thr_tcdrain(int fd) { - struct pthread *curthread = _get_curthread(); - int ret; + struct pthread *curthread; + int ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); - ret = __tcdrain(fd); + ret = __libc_tcdrain(fd); _thr_cancel_leave(curthread, ret == -1); return (ret); } -__weak_reference(___usleep, usleep); - -int -___usleep(useconds_t useconds) -{ - struct pthread *curthread = _get_curthread(); - int ret; - - _thr_cancel_enter(curthread); - ret = __usleep(useconds); - _thr_cancel_leave(curthread, 1); - - return (ret); -} - -__weak_reference(___wait, wait); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call returns * a child pid, the thread is not canceled. */ -pid_t -___wait(int *istat) +static pid_t +__thr_wait4(pid_t pid, int *status, int options, struct rusage *rusage) { - struct pthread *curthread = _get_curthread(); - pid_t ret; - - _thr_cancel_enter(curthread); - ret = __wait(istat); - _thr_cancel_leave(curthread, ret <= 0); - - return ret; -} - -__weak_reference(__wait3, wait3); - -/* - * Cancellation behavior: - * Thread may be canceled at start, but if the system call returns - * a child pid, the thread is not canceled. - */ -pid_t -__wait3(int *status, int options, struct rusage *rusage) -{ - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; pid_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); - ret = _wait4(WAIT_ANY, status, options, rusage); + ret = __sys_wait4(pid, status, options, rusage); _thr_cancel_leave(curthread, ret <= 0); - return (ret); } -__weak_reference(__wait4, wait4); - /* * Cancellation behavior: * Thread may be canceled at start, but if the system call returns * a child pid, the thread is not canceled. */ -pid_t -__wait4(pid_t pid, int *status, int options, struct rusage *rusage) +static pid_t +__thr_wait6(idtype_t idtype, id_t id, int *status, int options, + struct __wrusage *ru, siginfo_t *infop) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; pid_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); - ret = __sys_wait4(pid, status, options, rusage); - _thr_cancel_leave(curthread, ret <= 0); - - return ret; -} - -__weak_reference(___waitpid, waitpid); - -/* - * Cancellation behavior: - * Thread may be canceled at start, but if the system call returns - * a child pid, the thread is not canceled. - */ -pid_t -___waitpid(pid_t wpid, int *status, int options) -{ - struct pthread *curthread = _get_curthread(); - pid_t ret; - - _thr_cancel_enter(curthread); - ret = __waitpid(wpid, status, options); + ret = __sys_wait6(idtype, id, status, options, ru, infop); _thr_cancel_leave(curthread, ret <= 0); - - return ret; + return (ret); } -__weak_reference(__write, write); - /* * Cancellation behavior: * Thread may be canceled at start, but if the thread wrote some data, * it is not canceled. */ -ssize_t -__write(int fd, const void *buf, size_t nbytes) +static ssize_t +__thr_write(int fd, const void *buf, size_t nbytes) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; ssize_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_write(fd, buf, nbytes); _thr_cancel_leave(curthread, (ret <= 0)); - return ret; + return (ret); } -__weak_reference(__writev, writev); - /* * Cancellation behavior: * Thread may be canceled at start, but if the thread wrote some data, * it is not canceled. */ -ssize_t -__writev(int fd, const struct iovec *iov, int iovcnt) +static ssize_t +__thr_writev(int fd, const struct iovec *iov, int iovcnt) { - struct pthread *curthread = _get_curthread(); + struct pthread *curthread; ssize_t ret; + curthread = _get_curthread(); _thr_cancel_enter(curthread); ret = __sys_writev(fd, iov, iovcnt); _thr_cancel_leave(curthread, (ret <= 0)); - return ret; + return (ret); +} + +void +__thr_interpose_libc(void) +{ + + __set_error_selector(__error_threaded); +#define SLOT(name) \ + *(__libc_interposing_slot(INTERPOS_##name)) = \ + (interpos_func_t)__thr_##name; + SLOT(accept); + SLOT(accept4); + SLOT(aio_suspend); + SLOT(close); + SLOT(connect); + SLOT(fcntl); + SLOT(fsync); + SLOT(fork); + SLOT(msync); + SLOT(nanosleep); + SLOT(openat); + SLOT(poll); + SLOT(pselect); + SLOT(read); + SLOT(readv); + SLOT(recvfrom); + SLOT(recvmsg); + SLOT(select); + SLOT(sendmsg); + SLOT(sendto); + SLOT(setcontext); + SLOT(sigaction); + SLOT(sigprocmask); + SLOT(sigsuspend); + SLOT(sigwait); + SLOT(sigtimedwait); + SLOT(sigwaitinfo); + SLOT(swapcontext); + SLOT(system); + SLOT(tcdrain); + SLOT(wait4); + SLOT(write); + SLOT(writev); + SLOT(spinlock); + SLOT(spinunlock); + SLOT(kevent); + SLOT(wait6); + SLOT(ppoll); +#undef SLOT + *(__libc_interposing_slot( + INTERPOS__pthread_mutex_init_calloc_cb)) = + (interpos_func_t)_pthread_mutex_init_calloc_cb; } |