summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libthr/thread')
-rw-r--r--lib/libthr/thread/thr_create.c8
-rw-r--r--lib/libthr/thread/thr_fork.c6
-rw-r--r--lib/libthr/thread/thr_init.c10
-rw-r--r--lib/libthr/thread/thr_printf.c1
-rw-r--r--lib/libthr/thread/thr_private.h20
-rw-r--r--lib/libthr/thread/thr_sig.c177
-rw-r--r--lib/libthr/thread/thr_syscalls.c521
7 files changed, 295 insertions, 448 deletions
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_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_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..d62de98 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -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,29 @@ 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);
+
__END_DECLS
#endif /* !_THR_PRIVATE_H */
diff --git a/lib/libthr/thread/thr_sig.c b/lib/libthr/thread/thr_sig.c
index 57c9406..7cd0f75 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;
@@ -598,8 +609,6 @@ _pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
return (0);
}
-__weak_reference(__sigsuspend, sigsuspend);
-
int
_sigsuspend(const sigset_t * set)
{
@@ -609,7 +618,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 +642,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 +658,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 +686,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 +712,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 +726,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 +739,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 +756,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_syscalls.c b/lib/libthr/thread/thr_syscalls.c
index 7a08302..06b63c8 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,15 @@
#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,...);
+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 +113,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 +131,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 +146,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 +153,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 +167,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 +185,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,13 +192,14 @@ __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);
@@ -311,18 +221,17 @@ __fcntl(int fd, int cmd,...)
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 +239,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 +272,68 @@ __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,...)
-{
- struct pthread *curthread = _get_curthread();
- int ret;
- int mode = 0;
- va_list ap;
-
- /* 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);
- }
-
- _thr_cancel_enter(curthread);
- ret = __sys_open(path, flags, mode);
- _thr_cancel_leave(curthread, ret == -1);
-
- return ret;
-}
-
-__weak_reference(__openat, openat);
-
/*
* Cancellation behavior:
* If the thread is canceled, file is not opened.
*/
-int
-__openat(int fd, 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_openat(fd, path, flags, mode);
_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_poll(struct pollfd *fds, unsigned int nfds, int timeout)
{
- struct pthread *curthread = _get_curthread();
+ struct pthread *curthread;
int ret;
+ curthread = _get_curthread();
_thr_cancel_enter(curthread);
ret = __sys_poll(fds, nfds, timeout);
_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 +341,264 @@ ___pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
return (ret);
}
-__weak_reference(__read, read);
-
/*
* 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();
- pid_t ret;
-
- _thr_cancel_enter(curthread);
- ret = _wait4(WAIT_ANY, 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)
-{
- 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);
- _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);
+#undef SLOT
+ *(__libc_interposing_slot(
+ INTERPOS__pthread_mutex_init_calloc_cb)) =
+ (interpos_func_t)_pthread_mutex_init_calloc_cb;
}
OpenPOWER on IntegriCloud