diff options
36 files changed, 1381 insertions, 541 deletions
@@ -1,5 +1,17 @@ 2002-12-17 Jakub Jelinek <jakub@redhat.com> + * sysdeps/unix/sysv/linux/alpha/syscalls.list (msgrcv, msgsnd): + Make cancelable. + * sysdeps/unix/sysv/linux/hppa/syscalls.list (msgrcv, msgsnd): + Likewise. + * sysdeps/unix/sysv/linux/ia64/syscalls.list (msgrcv, msgsnd): + Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list (msgrcv, msgsnd): + Likewise. + * sysdeps/unix/sysv/linux/x86_64/syscalls.list (msgrcv, msgsnd): + Likewise. + * sysdeps/unix/sysv/linux/ia64/sigsuspend.c (__sigsuspend): Likewise. + * malloc/thread-m.h (mutex_init, mutex_lock, mutex_trylock, mutex_unlock): If not building NPTL, use __libc_maybe_call2 if available, otherwise __libc_maybe_call. diff --git a/linuxthreads/ChangeLog b/linuxthreads/ChangeLog index 179e247f2e..a84d4bd383 100644 --- a/linuxthreads/ChangeLog +++ b/linuxthreads/ChangeLog @@ -1,3 +1,122 @@ +2002-12-18 Jakub Jelinek <jakub@redhat.com> + + * internals.h (__pthread_thread_self): New prototype. + (struct pthread_functions): Add ptr_pthread_thread_self field. + * pthread.c (pthread_functions): Initialize ptr_pthread_thread_self. + (__pthread_thread_self): New function. + * libc-cancellation.c (__pthread_thread_self): Add weak_extern. + (__libc_enable_asynccancel, __libc_disable_asynccancel): Don't + use thread_self() directly if not FLOATING_STACKS. + +2002-12-18 Jakub Jelinek <jakub@redhat.com> + + * sysdeps/x86_64/pt-machine.h: Guard most of the header + with #ifndef __ASSEMBLER__. + * pthread.c (pthread_functions): Use SHLIB_COMPAT around + pthread_attr_init_2_0 use. + +2002-12-17 Jakub Jelinek <jakub@redhat.com> + + * wrapsyscall.c: Removed. + * weaks.c: Removed. + * Makefile (distribute): Add tst-cancel-wrappers.sh. + (routines): Remove weaks. Add forward, + libc_pthread_init, libc-cancellation. + (shared-only-routines): Remove weaks. Add forward. + (libpthread-routines): Remove wrapsyscall. + Add ptw-write, ptw-read, ptw-close, ptw-fcntl, ptw-accept, + ptw-connect, ptw-recv, ptw-recvfrom, ptw-recvmsg, ptw-send, + ptw-sendmsg, ptw-sendto, ptw-fsync, ptw-lseek, ptw-lseek64, + ptw-llseek, ptw-msync, ptw-nanosleep, ptw-open, ptw-open64, + ptw-pause, ptw-pread, ptw-pread64, ptw-pwrite, ptw-pwrite64, + ptw-tcdrain, ptw-wait, ptw-waitpid, pt-system, pt-allocrtsig. + (libpthread-shared-only-routines): Add pt-allocrtsig. + (tests): Depend on $(objpfx)tst-cancel-wrappers.out. + ($(objpfx)tst-cancel-wrappers.out): New rule. + * sysdeps/pthread/bits/libc-lock.h: Include linuxthreads/internals.h + if in libc. + (__libc_maybe_call): In libpthread.* don't check for existance + of the function. + (__libc_maybe_call2): Define. + (__libc_lock_init, __libc_lock_fini, __libc_lock_lock, + __libc_lock_trylock, __libc_lock_unlock): Use it. + * sysdeps/pthread/flockfile.c: New file. + * sysdeps/pthread/ftrylockfile.c: New file. + * sysdeps/pthread/funlockfile.c: New file. + * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h: New file. + * sysdeps/unix/sysv/linux/allocrtsig.c: New file. + * libc-cancellation.c: New file. + * forward.c: New file. + * libc_pthread_init.c: New file. + * pt-system.c: New file. + * pthread.c: Remove locale.h. + (__pthread_manager_thread): Initialize multiple_threads. + (__pthread_multiple_threads): Declare. + (pthread_functions): New variable. + (__pthread_initialize_minimal): Remove __uselocale call. + Call __libc_pthread_init. + (__pthread_initialize_manager): Initialize __pthread_multiple_threads, + initial thread's multiple_threads and __libc_multiple_threads. + Check MULTIPLE_THREADS_OFFSET value. Initialize manager thread's + multiple_threads. + (pthread_setschedparam, pthread_getschedparam): Rename to __ + prefixed variants. Add strong_alias. + (current_rtmin, current_rtmax, __libc_current_sigrtmin, + __libc_current_sigrtmax, __libc_allocate_rtsig): Remove. + (init_rtsigs): Use __libc_current_sigrtmin_private. + (pthread_initialize): Only call init_rtsigs if + !__ASSUME_REALTIME_SIGNALS. + (__pthread_require_wrappers, __pthread_require_lockfile): Remove. + * internals.h (__pthread_attr_destroy, __pthread_attr_setdetachstate, + __pthread_attr_getdetachstate, __pthread_attr_setschedparam, + __pthread_attr_getschedparam, __pthread_attr_setschedpolicy, + __pthread_attr_getschedpolicy, __pthread_attr_setinheritsched, + __pthread_attr_getinheritsched, __pthread_attr_setscope, + __pthread_attr_getscope, __pthread_cond_init, + __pthread_cond_destroy, __pthread_cond_wait, + __pthread_cond_signal, __pthread_cond_broadcast, + __pthread_condattr_init, __pthread_condattr_destroy, + __pthread_equal, __pthread_getschedparam, + __pthread_setschedparam, __pthread_setcancelstate, + __pthread_setcanceltype, __pthread_enable_asynccancel, + __libc_enable_asynccancel, __libc_pthread_init): New prototype. + (__pthread_mutex_init, __pthread_mutex_destroy, + __pthread_mutex_lock, __pthread_mutex_unlock, + __pthread_mutex_trylock): Likewise. + Add hidden_proto. + (struct pthread_functions): New type. + (__libc_pthread_functions): New variable. + (LIBC_CANCEL_ASYNC, LIBC_CANCEL_RESET): Define. + * descr.h (struct _pthread_descr_struct): Add + p_header.data.multiple_threads field. + * manager.c (pthread_handle_create): Initialize multiple_threads. + * cancel.c (__pthread_enable_asynccancel, + __pthread_disable_asynccancel): New functions. + (__pthread_provide_wrappers): Remove. + (pthread_setcancelstate, pthread_setcanceltype): Rename to __ + prefixed variants. Add strong_alias. + * condvar.c (pthread_cond_init, pthread_cond_destroy, + pthread_cond_wait, pthread_cond_signal, pthread_cond_broadcast, + pthread_condattr_init, pthread_condattr_destroy): Likewise. + * join.c (pthread_exit): Likewise. + * attr.c (pthread_attr_destroy, pthread_attr_setdetachstate, + pthread_attr_getdetachstate, pthread_attr_setschedparam, + pthread_attr_getschedparam, pthread_attr_setschedpolicy, + pthread_attr_getschedpolicy, pthread_attr_setinheritsched, + pthread_attr_getinheritsched, pthread_attr_setscope, + pthread_attr_getscope): Likewise. + * mutex.c (__pthread_mutex_init, __pthread_mutex_destroy, + __pthread_mutex_lock, __pthread_mutex_unlock, + __pthread_mutex_trylock): Add hidden_def. + * Versions (libc): Add __libc_pthread_init, + __libc_current_sigrtmin_private, __libc_current_sigrtmax_private, + __libc_allocate_rtsig_private @@GLIBC_PRIVATE. + * lockfile.c: Remove some USE_IN_LIBIO guards. + (__pthread_provide_lockfile): Remove. + * pt-allocrtsig.c: New file. + * tst-cancel-wrappers.sh: New test. + 2002-12-15 Ulrich Drepper <drepper@redhat.com> * Versions [libpthread: GLIBC_2.3.2]: Remove creat, poll, pselect, diff --git a/linuxthreads/Makefile b/linuxthreads/Makefile index fca0137571..7c993ac0fd 100644 --- a/linuxthreads/Makefile +++ b/linuxthreads/Makefile @@ -26,20 +26,29 @@ linuxthreads-version := $(shell sed -n 's/^.*$(subdir)-\([0-9.]*\).*$$/\1/p' \ headers := pthread.h semaphore.h distribute := internals.h queue.h restart.h spinlock.h smp.h tst-signal.sh \ - libc-tsd.c + tst-cancel-wrappers.sh libc-tsd.c -routines := weaks no-tsd -shared-only-routines = weaks +routines := forward no-tsd libc-cancellation libc_pthread_init +shared-only-routines = forward extra-libs := libpthread extra-libs-others := $(extra-libs) libpthread-routines := attr cancel condvar join manager mutex ptfork \ ptlongjmp pthread signals specific errno lockfile \ - semaphore spinlock wrapsyscall rwlock pt-machine \ + semaphore spinlock rwlock pt-machine \ oldsemaphore events getcpuclockid pspinlock barrier \ ptclock_gettime ptclock_settime sighandler \ - pthandles libc-tls-loc + pthandles libc-tls-loc pt-allocrtsig \ + ptw-write ptw-read ptw-close ptw-fcntl ptw-accept \ + ptw-connect ptw-recv ptw-recvfrom ptw-recvmsg \ + ptw-send ptw-sendmsg ptw-sendto ptw-fsync ptw-lseek \ + ptw-lseek64 ptw-llseek ptw-msync ptw-nanosleep \ + ptw-open ptw-open64 ptw-pause ptw-pread ptw-pread64 \ + ptw-pwrite ptw-pwrite64 ptw-tcdrain ptw-wait \ + ptw-waitpid pt-system + +libpthread-shared-only-routines = pt-allocrtsig nodelete-yes = -Wl,--enable-new-dtags,-z,nodelete initfirst-yes = -Wl,--enable-new-dtags,-z,initfirst @@ -194,8 +203,13 @@ endif ifeq (no,$(cross-compiling)) ifeq (yes,$(build-shared)) -tests: $(objpfx)tst-signal.out +tests: $(objpfx)tst-signal.out $(objpfx)tst-cancel-wrappers.out $(objpfx)tst-signal.out: tst-signal.sh $(objpfx)tst-signal $(SHELL) -e $< $(common-objpfx) > $@ +$(objpfx)tst-cancel-wrappers.out: tst-cancel-wrappers.sh + $(SHELL) $< $(common-objpfx)/libc_pic.a \ + $(common-objpfx)/libc.a \ + $(objpfx)/libpthread_pic.a \ + $(objpfx)/libpthread.a > $@ endif endif diff --git a/linuxthreads/Versions b/linuxthreads/Versions index 78b1a937cf..fea2e368d8 100644 --- a/linuxthreads/Versions +++ b/linuxthreads/Versions @@ -22,6 +22,9 @@ libc { __libc_internal_tsd_address; __libc_alloca_cutoff; __libc_dl_error_tsd; + __libc_pthread_init; __libc_current_sigrtmin_private; + __libc_current_sigrtmax_private; __libc_allocate_rtsig_private; + __libc_creat; __libc_poll; __libc_pselect; __libc_select; __libc_sigpause; __libc_sigsuspend; __libc_sigwait; __libc_sigwaitinfo; __libc_waitid; __libc___xpg_sigpause; diff --git a/linuxthreads/attr.c b/linuxthreads/attr.c index 8b7e8ce81c..58a7b69f94 100644 --- a/linuxthreads/attr.c +++ b/linuxthreads/attr.c @@ -56,12 +56,13 @@ compat_symbol (libpthread, __pthread_attr_init_2_0, pthread_attr_init, GLIBC_2_0); #endif -int pthread_attr_destroy(pthread_attr_t *attr) +int __pthread_attr_destroy(pthread_attr_t *attr) { return 0; } +strong_alias (__pthread_attr_destroy, pthread_attr_destroy); -int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) +int __pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) { if (detachstate < PTHREAD_CREATE_JOINABLE || detachstate > PTHREAD_CREATE_DETACHED) @@ -69,15 +70,17 @@ int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate) attr->__detachstate = detachstate; return 0; } +strong_alias (__pthread_attr_setdetachstate, pthread_attr_setdetachstate); -int pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) +int __pthread_attr_getdetachstate(const pthread_attr_t *attr, int *detachstate) { *detachstate = attr->__detachstate; return 0; } +strong_alias (__pthread_attr_getdetachstate, pthread_attr_getdetachstate); -int pthread_attr_setschedparam(pthread_attr_t *attr, - const struct sched_param *param) +int __pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param) { int max_prio = __sched_get_priority_max(attr->__schedpolicy); int min_prio = __sched_get_priority_min(attr->__schedpolicy); @@ -87,43 +90,49 @@ int pthread_attr_setschedparam(pthread_attr_t *attr, memcpy (&attr->__schedparam, param, sizeof (struct sched_param)); return 0; } +strong_alias (__pthread_attr_setschedparam, pthread_attr_setschedparam); -int pthread_attr_getschedparam(const pthread_attr_t *attr, - struct sched_param *param) +int __pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param) { memcpy (param, &attr->__schedparam, sizeof (struct sched_param)); return 0; } +strong_alias (__pthread_attr_getschedparam, pthread_attr_getschedparam); -int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) +int __pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy) { if (policy != SCHED_OTHER && policy != SCHED_FIFO && policy != SCHED_RR) return EINVAL; attr->__schedpolicy = policy; return 0; } +strong_alias (__pthread_attr_setschedpolicy, pthread_attr_setschedpolicy); -int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) +int __pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy) { *policy = attr->__schedpolicy; return 0; } +strong_alias (__pthread_attr_getschedpolicy, pthread_attr_getschedpolicy); -int pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) +int __pthread_attr_setinheritsched(pthread_attr_t *attr, int inherit) { if (inherit != PTHREAD_INHERIT_SCHED && inherit != PTHREAD_EXPLICIT_SCHED) return EINVAL; attr->__inheritsched = inherit; return 0; } +strong_alias (__pthread_attr_setinheritsched, pthread_attr_setinheritsched); -int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) +int __pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inherit) { *inherit = attr->__inheritsched; return 0; } +strong_alias (__pthread_attr_getinheritsched, pthread_attr_getinheritsched); -int pthread_attr_setscope(pthread_attr_t *attr, int scope) +int __pthread_attr_setscope(pthread_attr_t *attr, int scope) { switch (scope) { case PTHREAD_SCOPE_SYSTEM: @@ -135,12 +144,14 @@ int pthread_attr_setscope(pthread_attr_t *attr, int scope) return EINVAL; } } +strong_alias (__pthread_attr_setscope, pthread_attr_setscope); -int pthread_attr_getscope(const pthread_attr_t *attr, int *scope) +int __pthread_attr_getscope(const pthread_attr_t *attr, int *scope) { *scope = attr->__scope; return 0; } +strong_alias (__pthread_attr_getscope, pthread_attr_getscope); int __pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize) { diff --git a/linuxthreads/cancel.c b/linuxthreads/cancel.c index 47c0bfee04..838f55d8b2 100644 --- a/linuxthreads/cancel.c +++ b/linuxthreads/cancel.c @@ -30,7 +30,7 @@ #endif -int pthread_setcancelstate(int state, int * oldstate) +int __pthread_setcancelstate(int state, int * oldstate) { pthread_descr self = thread_self(); if (state < PTHREAD_CANCEL_ENABLE || state > PTHREAD_CANCEL_DISABLE) @@ -43,8 +43,9 @@ int pthread_setcancelstate(int state, int * oldstate) __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); return 0; } +strong_alias (__pthread_setcancelstate, pthread_setcancelstate); -int pthread_setcanceltype(int type, int * oldtype) +int __pthread_setcanceltype(int type, int * oldtype) { pthread_descr self = thread_self(); if (type < PTHREAD_CANCEL_DEFERRED || type > PTHREAD_CANCEL_ASYNCHRONOUS) @@ -57,6 +58,33 @@ int pthread_setcanceltype(int type, int * oldtype) __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); return 0; } +strong_alias (__pthread_setcanceltype, pthread_setcanceltype); + + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__pthread_enable_asynccancel (void) +{ + pthread_descr self = thread_self(); + int oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); + return oldtype; +} + +void +internal_function attribute_hidden +__pthread_disable_asynccancel (int oldtype) +{ + pthread_descr self = thread_self(); + THREAD_SETMEM(self, p_canceltype, oldtype); +} + int pthread_cancel(pthread_t thread) { @@ -210,14 +238,3 @@ void __pthread_perform_cleanup(char *currentframe) __rpc_thread_destroy (); #endif } - -#ifndef SHARED -/* We need a hook to force the cancelation wrappers and file locking - to be linked in when static libpthread is used. */ -extern const int __pthread_provide_wrappers; -static const int *const __pthread_require_wrappers = - &__pthread_provide_wrappers; -extern const int __pthread_provide_lockfile; -static const int *const __pthread_require_lockfile = - &__pthread_provide_lockfile; -#endif diff --git a/linuxthreads/condvar.c b/linuxthreads/condvar.c index fd0db50fa2..a40ae49fab 100644 --- a/linuxthreads/condvar.c +++ b/linuxthreads/condvar.c @@ -25,19 +25,21 @@ #include "queue.h" #include "restart.h" -int pthread_cond_init(pthread_cond_t *cond, - const pthread_condattr_t *cond_attr) +int __pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *cond_attr) { __pthread_init_lock(&cond->__c_lock); cond->__c_waiting = NULL; return 0; } +strong_alias (__pthread_cond_init, pthread_cond_init) -int pthread_cond_destroy(pthread_cond_t *cond) +int __pthread_cond_destroy(pthread_cond_t *cond) { if (cond->__c_waiting != NULL) return EBUSY; return 0; } +strong_alias (__pthread_cond_destroy, pthread_cond_destroy) /* Function called by pthread_cancel to remove the thread from waiting on a condition variable queue. */ @@ -55,7 +57,7 @@ static int cond_extricate_func(void *obj, pthread_descr th) return did_remove; } -int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) +int __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) { volatile pthread_descr self = thread_self(); pthread_extricate_if extr; @@ -132,6 +134,7 @@ int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex) pthread_mutex_lock(mutex); return 0; } +strong_alias (__pthread_cond_wait, pthread_cond_wait) static int pthread_cond_timedwait_relative(pthread_cond_t *cond, @@ -234,7 +237,7 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, return pthread_cond_timedwait_relative(cond, mutex, abstime); } -int pthread_cond_signal(pthread_cond_t *cond) +int __pthread_cond_signal(pthread_cond_t *cond) { pthread_descr th; @@ -248,8 +251,9 @@ int pthread_cond_signal(pthread_cond_t *cond) } return 0; } +strong_alias (__pthread_cond_signal, pthread_cond_signal) -int pthread_cond_broadcast(pthread_cond_t *cond) +int __pthread_cond_broadcast(pthread_cond_t *cond) { pthread_descr tosignal, th; @@ -266,16 +270,19 @@ int pthread_cond_broadcast(pthread_cond_t *cond) } return 0; } +strong_alias (__pthread_cond_broadcast, pthread_cond_broadcast) -int pthread_condattr_init(pthread_condattr_t *attr) +int __pthread_condattr_init(pthread_condattr_t *attr) { return 0; } +strong_alias (__pthread_condattr_init, pthread_condattr_init) -int pthread_condattr_destroy(pthread_condattr_t *attr) +int __pthread_condattr_destroy(pthread_condattr_t *attr) { return 0; } +strong_alias (__pthread_condattr_destroy, pthread_condattr_destroy) int pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared) { diff --git a/linuxthreads/descr.h b/linuxthreads/descr.h index 1e14823d83..94ad893979 100644 --- a/linuxthreads/descr.h +++ b/linuxthreads/descr.h @@ -106,6 +106,7 @@ struct _pthread_descr_struct { the address of this thread descriptor. */ union dtv *dtvp; pthread_descr self; /* Pointer to this structure */ + int multiple_threads; } data; void *__padding[16]; } p_header; diff --git a/linuxthreads/forward.c b/linuxthreads/forward.c new file mode 100644 index 0000000000..499930ab26 --- /dev/null +++ b/linuxthreads/forward.c @@ -0,0 +1,146 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <dlfcn.h> +#include "internals.h" +#include <stdlib.h> + +#include <shlib-compat.h> + + +/* Pointers to the libc functions. */ +struct pthread_functions __libc_pthread_functions attribute_hidden; + + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_3_2) +# define FORWARD4(name, export, rettype, decl, params, defaction, version) \ +rettype \ +__noexport_##name decl \ +{ \ + if (__libc_pthread_functions.ptr_##name == NULL) \ + defaction; \ + \ + return __libc_pthread_functions.ptr_##name params; \ +} \ +compat_symbol (libc, __noexport_##name, export, version) + +# define FORWARD3(name, rettype, decl, params, defaction, version) \ + FORWARD4 (name, name, rettype, decl, params, defaction, version) + +# define FORWARD2(name, decl, params, defretval, version) \ + FORWARD3 (name, int, decl, params, return defretval, version) + +# define FORWARD(name, decl, params, defretval) \ + FORWARD2 (name, decl, params, defretval, GLIBC_2_0) + + +FORWARD (pthread_attr_destroy, (pthread_attr_t *attr), (attr), 0); + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_1) +FORWARD4 (pthread_attr_init_2_0, pthread_attr_init, int, + (pthread_attr_t *attr), (attr), 0, GLIBC_2_0); +#endif + +FORWARD4 (pthread_attr_init_2_1, pthread_attr_init, int, + (pthread_attr_t *attr), (attr), 0, GLIBC_2_1); + +FORWARD (pthread_attr_getdetachstate, + (const pthread_attr_t *attr, int *detachstate), (attr, detachstate), + 0); +FORWARD (pthread_attr_setdetachstate, (pthread_attr_t *attr, int detachstate), + (attr, detachstate), 0); + +FORWARD (pthread_attr_getinheritsched, + (const pthread_attr_t *attr, int *inherit), (attr, inherit), 0); +FORWARD (pthread_attr_setinheritsched, (pthread_attr_t *attr, int inherit), + (attr, inherit), 0); + +FORWARD (pthread_attr_getschedparam, + (const pthread_attr_t *attr, struct sched_param *param), + (attr, param), 0); +FORWARD (pthread_attr_setschedparam, + (pthread_attr_t *attr, const struct sched_param *param), + (attr, param), 0); + +FORWARD (pthread_attr_getschedpolicy, + (const pthread_attr_t *attr, int *policy), (attr, policy), 0); +FORWARD (pthread_attr_setschedpolicy, (pthread_attr_t *attr, int policy), + (attr, policy), 0); + +FORWARD (pthread_attr_getscope, + (const pthread_attr_t *attr, int *scope), (attr, scope), 0); +FORWARD (pthread_attr_setscope, (pthread_attr_t *attr, int scope), + (attr, scope), 0); + + +FORWARD (pthread_condattr_destroy, (pthread_condattr_t *attr), (attr), 0); +FORWARD (pthread_condattr_init, (pthread_condattr_t *attr), (attr), 0); + + +FORWARD (pthread_cond_broadcast, (pthread_cond_t *cond), (cond), 0); + +FORWARD (pthread_cond_destroy, (pthread_cond_t *cond), (cond), 0); + +FORWARD (pthread_cond_init, + (pthread_cond_t *cond, const pthread_condattr_t *cond_attr), + (cond, cond_attr), 0); + +FORWARD (pthread_cond_signal, (pthread_cond_t *cond), (cond), 0); + +FORWARD (pthread_cond_wait, (pthread_cond_t *cond, pthread_mutex_t *mutex), + (cond, mutex), 0); + + +FORWARD (pthread_equal, (pthread_t thread1, pthread_t thread2), + (thread1, thread2), 1); + + +FORWARD3 (pthread_exit, void, (void *retval), (retval), exit (EXIT_SUCCESS), + GLIBC_2_0); + + +FORWARD (pthread_getschedparam, + (pthread_t target_thread, int *policy, struct sched_param *param), + (target_thread, policy, param), 0); +FORWARD (pthread_setschedparam, + (pthread_t target_thread, int policy, + const struct sched_param *param), (target_thread, policy, param), 0); + + +FORWARD (pthread_mutex_destroy, (pthread_mutex_t *mutex), (mutex), 0); + +FORWARD (pthread_mutex_init, + (pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr), + (mutex, mutexattr), 0); + +FORWARD (pthread_mutex_lock, (pthread_mutex_t *mutex), (mutex), 0); + +FORWARD (pthread_mutex_unlock, (pthread_mutex_t *mutex), (mutex), 0); + + +FORWARD3 (pthread_self, pthread_t, (void), (), return 0, GLIBC_2_0); + + +FORWARD (pthread_setcancelstate, (int state, int *oldstate), (state, oldstate), + 0); + +FORWARD (pthread_setcanceltype, (int type, int *oldtype), (type, oldtype), 0); + + +#endif diff --git a/linuxthreads/internals.h b/linuxthreads/internals.h index 58a60fffc2..3e10304c2f 100644 --- a/linuxthreads/internals.h +++ b/linuxthreads/internals.h @@ -245,6 +245,9 @@ static inline int nonexisting_handle(pthread_handle h, pthread_t id) #define SPIN_SLEEP_DURATION 2000001 #endif +/* Defined and used in libc.so. */ +extern int __libc_multiple_threads attribute_hidden; + /* Debugging */ #ifdef DEBUG @@ -294,6 +297,24 @@ extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr, size_t __stacksize); extern int __pthread_attr_getstack (const pthread_attr_t *__attr, void **__stackaddr, size_t *__stacksize); +extern int __pthread_attr_destroy (pthread_attr_t *attr); +extern int __pthread_attr_setdetachstate (pthread_attr_t *attr, + int detachstate); +extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr, + int *detachstate); +extern int __pthread_attr_setschedparam (pthread_attr_t *attr, + const struct sched_param *param); +extern int __pthread_attr_getschedparam (const pthread_attr_t *attr, + struct sched_param *param); +extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy); +extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr, + int *policy); +extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit); +extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr, + int *inherit); +extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope); +extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope); + extern int __pthread_getconcurrency (void); extern int __pthread_setconcurrency (int __level); extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex, @@ -305,6 +326,37 @@ extern int __pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr, extern int __pthread_mutexattr_gettype (const pthread_mutexattr_t *__attr, int *__kind); extern void __pthread_kill_other_threads_np (void); +extern int __pthread_mutex_init (pthread_mutex_t *__mutex, + __const pthread_mutexattr_t *__mutex_attr); +extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex); +extern int __pthread_mutex_lock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_trylock (pthread_mutex_t *__mutex); +extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex); +#if defined NOT_IN_libc && defined IS_IN_libpthread +hidden_proto (__pthread_mutex_init) +hidden_proto (__pthread_mutex_destroy) +hidden_proto (__pthread_mutex_lock) +hidden_proto (__pthread_mutex_trylock) +hidden_proto (__pthread_mutex_unlock) +#endif +extern int __pthread_cond_init (pthread_cond_t *cond, + const pthread_condattr_t *cond_attr); +extern int __pthread_cond_destroy (pthread_cond_t *cond); +extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex); +extern int __pthread_cond_signal (pthread_cond_t *cond); +extern int __pthread_cond_broadcast (pthread_cond_t *cond); +extern int __pthread_condattr_init (pthread_condattr_t *attr); +extern int __pthread_condattr_destroy (pthread_condattr_t *attr); +extern pthread_t __pthread_self (void); +extern pthread_descr __pthread_thread_self (void); +extern int __pthread_equal (pthread_t thread1, pthread_t thread2); +extern void __pthread_exit (void *retval); +extern int __pthread_getschedparam (pthread_t thread, int *policy, + struct sched_param *param); +extern int __pthread_setschedparam (pthread_t thread, int policy, + const struct sched_param *param); +extern int __pthread_setcancelstate (int state, int * oldstate); +extern int __pthread_setcanceltype (int type, int * oldtype); extern void __pthread_restart_old(pthread_descr th); extern void __pthread_suspend_old(pthread_descr self); @@ -339,7 +391,6 @@ extern int __pthread_spin_destroy (pthread_spinlock_t *__lock); extern int __pthread_clock_gettime (hp_timing_t freq, struct timespec *tp); extern void __pthread_clock_settime (hp_timing_t offset); - /* Global pointers to old or new suspend functions */ extern void (*__pthread_restart)(pthread_descr); @@ -386,4 +437,77 @@ extern void __pthread_sighandler_rt(int signo, struct siginfo *si, struct ucontext *uc); extern void __pthread_null_sighandler(int sig); +/* Cancellation. */ +extern int __pthread_enable_asynccancel (void) attribute_hidden; +extern void __pthread_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +/* The two functions are in libc.so and not exported. */ +extern int __libc_enable_asynccancel (void) attribute_hidden; +extern void __libc_disable_asynccancel (int oldtype) + internal_function attribute_hidden; + +#if !defined NOT_IN_libc +# define LIBC_CANCEL_ASYNC() \ + __libc_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __libc_disable_asynccancel (oldtype) +#elif defined NOT_IN_libc && defined IS_IN_libpthread +# define LIBC_CANCEL_ASYNC() \ + __pthread_enable_asynccancel () +# define LIBC_CANCEL_RESET(oldtype) \ + __pthread_disable_asynccancel (oldtype) +#else +# define LIBC_CANCEL_ASYNC() 0 /* Just a dummy value. */ +# define LIBC_CANCEL_RESET(val) ((void)(val)) /* Nothing, but evaluate it. */ +#endif + +/* Data type shared with libc. The libc uses it to pass on calls to + the thread functions. */ +struct pthread_functions +{ + int (*ptr_pthread_attr_destroy) (pthread_attr_t *); + int (*ptr_pthread_attr_init_2_0) (pthread_attr_t *); + int (*ptr_pthread_attr_init_2_1) (pthread_attr_t *); + int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *, + struct sched_param *); + int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *, + const struct sched_param *); + int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int); + int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *); + int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int); + int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *); + int (*ptr_pthread_condattr_init) (pthread_condattr_t *); + int (*ptr_pthread_cond_broadcast) (pthread_cond_t *); + int (*ptr_pthread_cond_destroy) (pthread_cond_t *); + int (*ptr_pthread_cond_init) (pthread_cond_t *, const pthread_condattr_t *); + int (*ptr_pthread_cond_signal) (pthread_cond_t *); + int (*ptr_pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *); + int (*ptr_pthread_equal) (pthread_t, pthread_t); + void (*ptr_pthread_exit) (void *); + int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *); + int (*ptr_pthread_setschedparam) (pthread_t, int, + const struct sched_param *); + int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *); + int (*ptr_pthread_mutex_init) (pthread_mutex_t *, + const pthread_mutexattr_t *); + int (*ptr_pthread_mutex_lock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_trylock) (pthread_mutex_t *); + int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *); + pthread_t (*ptr_pthread_self) (void); + int (*ptr_pthread_setcancelstate) (int, int *); + int (*ptr_pthread_setcanceltype) (int, int *); + void (*ptr_pthread_do_exit) (void *retval, char *currentframe); + pthread_descr (*ptr_pthread_thread_self) (void); +}; + +/* Variable in libc.so. */ +extern struct pthread_functions __libc_pthread_functions attribute_hidden; +extern int * __libc_pthread_init (const struct pthread_functions *functions); + #endif /* internals.h */ diff --git a/linuxthreads/join.c b/linuxthreads/join.c index a6ed08c97a..3d204296fc 100644 --- a/linuxthreads/join.c +++ b/linuxthreads/join.c @@ -23,10 +23,11 @@ #include "spinlock.h" #include "restart.h" -void pthread_exit(void * retval) +void __pthread_exit(void * retval) { __pthread_do_exit (retval, CURRENT_STACK_FRAME); } +strong_alias (__pthread_exit, pthread_exit); void __pthread_do_exit(void *retval, char *currentframe) { diff --git a/linuxthreads/libc-cancellation.c b/linuxthreads/libc-cancellation.c new file mode 100644 index 0000000000..4d38d4222d --- /dev/null +++ b/linuxthreads/libc-cancellation.c @@ -0,0 +1,75 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <rpc/rpc.h> +#include "pthread.h" +#include "internals.h" +#include "spinlock.h" +#include "restart.h" +#include <bits/libc-lock.h> + +#if !defined NOT_IN_libc + +# ifndef SHARED +weak_extern (__pthread_do_exit) +weak_extern (__pthread_thread_self) +# endif + +int __libc_multiple_threads attribute_hidden; + +/* The next two functions are similar to pthread_setcanceltype() but + more specialized for the use in the cancelable functions like write(). + They do not need to check parameters etc. */ +int +attribute_hidden +__libc_enable_asynccancel (void) +{ +#ifdef FLOATING_STACKS + pthread_descr self = thread_self(); +#else + pthread_descr self = __libc_maybe_call2 (pthread_thread_self, (), NULL); + + if (self == NULL) + return PTHREAD_CANCEL_DEFERRED; +#endif + int oldtype = THREAD_GETMEM(self, p_canceltype); + THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_ASYNCHRONOUS); + if (__builtin_expect (THREAD_GETMEM(self, p_canceled), 0) && + THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) + __libc_maybe_call2 (pthread_do_exit, + (PTHREAD_CANCELED, CURRENT_STACK_FRAME), 0); + return oldtype; +} + +void +internal_function attribute_hidden +__libc_disable_asynccancel (int oldtype) +{ +#ifdef FLOATING_STACKS + pthread_descr self = thread_self(); +#else + pthread_descr self = __libc_maybe_call2 (pthread_thread_self, (), NULL); + + if (self != NULL) +#endif + THREAD_SETMEM(self, p_canceltype, oldtype); +} + +#endif diff --git a/linuxthreads/libc_pthread_init.c b/linuxthreads/libc_pthread_init.c new file mode 100644 index 0000000000..901d333fbf --- /dev/null +++ b/linuxthreads/libc_pthread_init.c @@ -0,0 +1,53 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <string.h> +#include <tls.h> +#include <locale.h> +#include "internals.h" +#include <sysdep-cancel.h> + +int * +__libc_pthread_init (functions) + const struct pthread_functions *functions; +{ +#ifdef SHARED + /* We copy the content of the variable pointed to by the FUNCTIONS + parameter to one in libc.so since this means access to the array + can be done with one memory access instead of two. */ + memcpy (&__libc_pthread_functions, functions, + sizeof (__libc_pthread_functions)); +#endif + +#ifdef MULTIPLE_THREADS_OFFSET + /* We have a macro which is used in asm code describing data layout. + Make sure it does not get out of date. */ + if (offsetof (struct _pthread_descr_struct, p_header.data.multiple_threads) + != MULTIPLE_THREADS_OFFSET) + abort (); +#endif + +#if !(USE_TLS && HAVE___THREAD) + /* Initialize thread-locale current locale to point to the global one. + With __thread support, the variable's initializer takes care of this. */ + __uselocale (LC_GLOBAL_LOCALE); +#endif + + return &__libc_multiple_threads; +} diff --git a/linuxthreads/lockfile.c b/linuxthreads/lockfile.c index 0e27324034..34055e4115 100644 --- a/linuxthreads/lockfile.c +++ b/linuxthreads/lockfile.c @@ -21,80 +21,51 @@ #include <stdio.h> #include <pthread.h> #include "internals.h" - -#ifdef USE_IN_LIBIO #include "../libio/libioP.h" -#endif - -#ifndef SHARED -/* We need a hook to force this file to be linked in when static - libpthread is used. */ -const int __pthread_provide_lockfile = 0; -#endif void __flockfile (FILE *stream) { -#ifdef USE_IN_LIBIO __pthread_mutex_lock (stream->_lock); -#else -#endif } -#ifdef USE_IN_LIBIO #undef _IO_flockfile strong_alias (__flockfile, _IO_flockfile) -#endif weak_alias (__flockfile, flockfile); void __funlockfile (FILE *stream) { -#ifdef USE_IN_LIBIO __pthread_mutex_unlock (stream->_lock); -#else -#endif } -#ifdef USE_IN_LIBIO #undef _IO_funlockfile strong_alias (__funlockfile, _IO_funlockfile) -#endif weak_alias (__funlockfile, funlockfile); int __ftrylockfile (FILE *stream) { -#ifdef USE_IN_LIBIO return __pthread_mutex_trylock (stream->_lock); -#else -#endif } -#ifdef USE_IN_LIBIO strong_alias (__ftrylockfile, _IO_ftrylockfile) -#endif weak_alias (__ftrylockfile, ftrylockfile); void __flockfilelist(void) { -#ifdef USE_IN_LIBIO _IO_list_lock(); -#endif } void __funlockfilelist(void) { -#ifdef USE_IN_LIBIO _IO_list_unlock(); -#endif } void __fresetlockfiles (void) { -#ifdef USE_IN_LIBIO _IO_ITER i; pthread_mutexattr_t attr; @@ -108,5 +79,4 @@ __fresetlockfiles (void) __pthread_mutexattr_destroy (&attr); _IO_list_resetlock(); -#endif } diff --git a/linuxthreads/manager.c b/linuxthreads/manager.c index 1d21760cf9..3268ea8a41 100644 --- a/linuxthreads/manager.c +++ b/linuxthreads/manager.c @@ -633,6 +633,7 @@ static int pthread_handle_create(pthread_t *thread, const pthread_attr_t *attr, initialized to zero already have this value. */ new_thread->p_header.data.tcb = new_thread; new_thread->p_header.data.self = new_thread; + new_thread->p_header.data.multiple_threads = 1; new_thread->p_tid = new_thread_id; new_thread->p_lock = &(__pthread_handles[sseg].h_lock); new_thread->p_cancelstate = PTHREAD_CANCEL_ENABLE; diff --git a/linuxthreads/mutex.c b/linuxthreads/mutex.c index 3c97ea7d66..d5f7a335cc 100644 --- a/linuxthreads/mutex.c +++ b/linuxthreads/mutex.c @@ -36,6 +36,7 @@ int __pthread_mutex_init(pthread_mutex_t * mutex, return 0; } strong_alias (__pthread_mutex_init, pthread_mutex_init) +hidden_def (__pthread_mutex_init) int __pthread_mutex_destroy(pthread_mutex_t * mutex) { @@ -55,6 +56,7 @@ int __pthread_mutex_destroy(pthread_mutex_t * mutex) } } strong_alias (__pthread_mutex_destroy, pthread_mutex_destroy) +hidden_def (__pthread_mutex_destroy) int __pthread_mutex_trylock(pthread_mutex_t * mutex) { @@ -91,6 +93,7 @@ int __pthread_mutex_trylock(pthread_mutex_t * mutex) } } strong_alias (__pthread_mutex_trylock, pthread_mutex_trylock) +hidden_def (__pthread_mutex_trylock) int __pthread_mutex_lock(pthread_mutex_t * mutex) { @@ -124,6 +127,7 @@ int __pthread_mutex_lock(pthread_mutex_t * mutex) } } strong_alias (__pthread_mutex_lock, pthread_mutex_lock) +hidden_def (__pthread_mutex_lock) int __pthread_mutex_timedlock (pthread_mutex_t *mutex, const struct timespec *abstime) @@ -199,6 +203,7 @@ int __pthread_mutex_unlock(pthread_mutex_t * mutex) } } strong_alias (__pthread_mutex_unlock, pthread_mutex_unlock) +hidden_def (__pthread_mutex_unlock) int __pthread_mutexattr_init(pthread_mutexattr_t *attr) { diff --git a/linuxthreads/pt-allocrtsig.c b/linuxthreads/pt-allocrtsig.c new file mode 100644 index 0000000000..3598dbb49f --- /dev/null +++ b/linuxthreads/pt-allocrtsig.c @@ -0,0 +1,50 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <signal.h> + + +/* These are defined in libc. We want to have only one definition + so we "forward" the calls. */ +extern int __libc_current_sigrtmin_private (void); +extern int __libc_current_sigrtmax_private (void); +extern int __libc_allocate_rtsig_private (int high); + + +/* We reserve __SIGRTMIN for use as the cancelation signal. This + signal is used internally. */ +int +__libc_current_sigrtmin (void) +{ + return __libc_current_sigrtmin_private (); +} + + +int +__libc_current_sigrtmax (void) +{ + return __libc_current_sigrtmax_private (); +} + + +int +__libc_allocate_rtsig (int high) +{ + return __libc_allocate_rtsig_private (high); +} diff --git a/linuxthreads/pt-system.c b/linuxthreads/pt-system.c new file mode 100644 index 0000000000..bc5098adc0 --- /dev/null +++ b/linuxthreads/pt-system.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <stdlib.h> +#include <sysdep-cancel.h> + + +int +system (const char *line) +{ + int oldtype = LIBC_CANCEL_ASYNC (); + int result = __libc_system (line); + LIBC_CANCEL_RESET (oldtype); + return result; +} diff --git a/linuxthreads/pthread.c b/linuxthreads/pthread.c index 8216985972..7fc5ef6ff4 100644 --- a/linuxthreads/pthread.c +++ b/linuxthreads/pthread.c @@ -33,12 +33,11 @@ #include "smp.h" #include <ldsodefs.h> #include <tls.h> -#include <locale.h> /* for __uselocale */ #include <version.h> /* Sanity check. */ -#if __ASSUME_REALTIME_SIGNALS && !defined __SIGRTMIN -# error "This must not happen; new kernel assumed but old headers" +#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3 +# error "This must not happen" #endif #if !(USE_TLS && HAVE___THREAD) @@ -86,6 +85,7 @@ struct _pthread_descr_struct __pthread_initial_thread = { #define manager_thread (&__pthread_manager_thread) struct _pthread_descr_struct __pthread_manager_thread = { .p_header.data.self = &__pthread_manager_thread, + .p_header.data.multiple_threads = 1, .p_lock = &__pthread_handles[1].h_lock, .p_start_args = PTHREAD_START_ARGS_INITIALIZER(__pthread_manager), #if !(USE_TLS && HAVE___THREAD) @@ -116,6 +116,8 @@ char *__pthread_initial_thread_bos; int __pthread_manager_request = -1; +int __pthread_multiple_threads attribute_hidden; + /* Other end of the pipe for sending requests to the thread manager. */ int __pthread_manager_reader; @@ -177,109 +179,38 @@ static void pthread_handle_sigdebug(int sig); platform does not support any real-time signals we will define the values to some unreasonable value which will signal failing of all the functions below. */ -#ifndef __SIGRTMIN -static int current_rtmin = -1; -static int current_rtmax = -1; -int __pthread_sig_restart = SIGUSR1; -int __pthread_sig_cancel = SIGUSR2; -int __pthread_sig_debug; -#else -static int current_rtmin; -static int current_rtmax; - -#if __SIGRTMAX - __SIGRTMIN >= 3 int __pthread_sig_restart = __SIGRTMIN; int __pthread_sig_cancel = __SIGRTMIN + 1; int __pthread_sig_debug = __SIGRTMIN + 2; -#else -int __pthread_sig_restart = SIGUSR1; -int __pthread_sig_cancel = SIGUSR2; -int __pthread_sig_debug; -#endif -static int rtsigs_initialized; +extern int __libc_current_sigrtmin_private (void); #if !__ASSUME_REALTIME_SIGNALS -# include "testrtsig.h" -#endif +static int rtsigs_initialized; static void init_rtsigs (void) { -#if !__ASSUME_REALTIME_SIGNALS - if (__builtin_expect (!kernel_has_rtsig (), 0)) + if (rtsigs_initialized) + return; + + if (__builtin_expect (__libc_current_sigrtmin_private () == -1)) { - current_rtmin = -1; - current_rtmax = -1; -# if __SIGRTMAX - __SIGRTMIN >= 3 __pthread_sig_restart = SIGUSR1; __pthread_sig_cancel = SIGUSR2; __pthread_sig_debug = 0; -# endif } else -#endif /* __ASSUME_REALTIME_SIGNALS */ { -#if __SIGRTMAX - __SIGRTMIN >= 3 - current_rtmin = __SIGRTMIN + 3; -# if !__ASSUME_REALTIME_SIGNALS __pthread_restart = __pthread_restart_new; __pthread_suspend = __pthread_wait_for_restart_signal; __pthread_timedsuspend = __pthread_timedsuspend_new; -# endif /* __ASSUME_REALTIME_SIGNALS */ -#else - current_rtmin = __SIGRTMIN; -#endif - - current_rtmax = __SIGRTMAX; } rtsigs_initialized = 1; } #endif -/* Return number of available real-time signal with highest priority. */ -int -__libc_current_sigrtmin (void) -{ -#ifdef __SIGRTMIN - if (__builtin_expect (!rtsigs_initialized, 0)) - init_rtsigs (); -#endif - return current_rtmin; -} - -/* Return number of available real-time signal with lowest priority. */ -int -__libc_current_sigrtmax (void) -{ -#ifdef __SIGRTMIN - if (__builtin_expect (!rtsigs_initialized, 0)) - init_rtsigs (); -#endif - return current_rtmax; -} - -/* Allocate real-time signal with highest/lowest available - priority. Please note that we don't use a lock since we assume - this function to be called at program start. */ -int -__libc_allocate_rtsig (int high) -{ -#ifndef __SIGRTMIN - return -1; -#else - if (__builtin_expect (!rtsigs_initialized, 0)) - init_rtsigs (); - if (__builtin_expect (current_rtmin == -1, 0) - || __builtin_expect (current_rtmin > current_rtmax, 0)) - /* We don't have anymore signal available. */ - return -1; - - return high ? current_rtmin++ : current_rtmax--; -#endif -} - /* Initialize the pthread library. Initialization is split in two functions: @@ -299,6 +230,52 @@ extern void *__dso_handle __attribute__ ((weak)); extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); #endif +#ifdef SHARED +static struct pthread_functions pthread_functions = + { + .ptr_pthread_attr_destroy = __pthread_attr_destroy, +#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) + .ptr_pthread_attr_init_2_0 = __pthread_attr_init_2_0, +#endif + .ptr_pthread_attr_init_2_1 = __pthread_attr_init_2_1, + .ptr_pthread_attr_getdetachstate = __pthread_attr_getdetachstate, + .ptr_pthread_attr_setdetachstate = __pthread_attr_setdetachstate, + .ptr_pthread_attr_getinheritsched = __pthread_attr_getinheritsched, + .ptr_pthread_attr_setinheritsched = __pthread_attr_setinheritsched, + .ptr_pthread_attr_getschedparam = __pthread_attr_getschedparam, + .ptr_pthread_attr_setschedparam = __pthread_attr_setschedparam, + .ptr_pthread_attr_getschedpolicy = __pthread_attr_getschedpolicy, + .ptr_pthread_attr_setschedpolicy = __pthread_attr_setschedpolicy, + .ptr_pthread_attr_getscope = __pthread_attr_getscope, + .ptr_pthread_attr_setscope = __pthread_attr_setscope, + .ptr_pthread_condattr_destroy = __pthread_condattr_destroy, + .ptr_pthread_condattr_init = __pthread_condattr_init, + .ptr_pthread_cond_broadcast = __pthread_cond_broadcast, + .ptr_pthread_cond_destroy = __pthread_cond_destroy, + .ptr_pthread_cond_init = __pthread_cond_init, + .ptr_pthread_cond_signal = __pthread_cond_signal, + .ptr_pthread_cond_wait = __pthread_cond_wait, + .ptr_pthread_equal = __pthread_equal, + .ptr_pthread_exit = __pthread_exit, + .ptr_pthread_getschedparam = __pthread_getschedparam, + .ptr_pthread_setschedparam = __pthread_setschedparam, + .ptr_pthread_mutex_destroy = __pthread_mutex_destroy, + .ptr_pthread_mutex_init = __pthread_mutex_init, + .ptr_pthread_mutex_lock = __pthread_mutex_lock, + .ptr_pthread_mutex_trylock = __pthread_mutex_trylock, + .ptr_pthread_mutex_unlock = __pthread_mutex_unlock, + .ptr_pthread_self = __pthread_self, + .ptr_pthread_setcancelstate = __pthread_setcancelstate, + .ptr_pthread_setcanceltype = __pthread_setcanceltype, + .ptr_pthread_do_exit = __pthread_do_exit, + .ptr_pthread_thread_self = __pthread_thread_self + }; +# define ptr_pthread_functions &pthread_functions +#else +# define ptr_pthread_functions NULL +#endif + +static int *__libc_multiple_threads_ptr; /* Do some minimal initialization which has to be done during the startup of the C library. */ @@ -413,11 +390,7 @@ cannot allocate TLS data structures for initial thread\n"; # endif #endif -#if !(USE_TLS && HAVE___THREAD) - /* Initialize thread-locale current locale to point to the global one. - With __thread support, the variable's initializer takes care of this. */ - __uselocale (LC_GLOBAL_LOCALE); -#endif + __libc_multiple_threads_ptr = __libc_pthread_init (ptr_pthread_functions); } @@ -520,7 +493,7 @@ static void pthread_initialize(void) /* Likewise for the resolver state _res. */ __pthread_initial_thread.p_resp = &_res; #endif -#ifdef __SIGRTMIN +#if !__ASSUME_REALTIME_SIGNALS /* Initialize real-time signals. */ init_rtsigs (); #endif @@ -577,6 +550,15 @@ int __pthread_initialize_manager(void) int report_events; pthread_descr tcb; + __pthread_multiple_threads = 1; + __pthread_main_thread->p_header.data.multiple_threads = 1; + * __libc_multiple_threads_ptr = 1; +#ifdef MULTIPLE_THREADS_OFFSET + if (offsetof(struct _pthread_descr_struct, p_header.data.multiple_threads) + != MULTIPLE_THREADS_OFFSET) + abort (); +#endif + #ifndef HAVE_Z_NODELETE if (__builtin_expect (&__dso_handle != NULL, 1)) __cxa_atexit ((void (*) (void *)) pthread_atexit_retcode, NULL, @@ -613,6 +595,7 @@ int __pthread_initialize_manager(void) /* Initialize the descriptor. */ tcb->p_header.data.tcb = tcb; tcb->p_header.data.self = tcb; + tcb->p_header.data.multiple_threads = 1; tcb->p_lock = &__pthread_handles[1].h_lock; # ifndef HAVE___THREAD tcb->p_errnop = &tcb->p_errno; @@ -797,16 +780,23 @@ compat_symbol (libpthread, __pthread_create_2_0, pthread_create, GLIBC_2_0); /* Simple operations on thread identifiers */ -pthread_t pthread_self(void) +pthread_descr __pthread_thread_self(void) +{ + return thread_self(); +} + +pthread_t __pthread_self(void) { pthread_descr self = thread_self(); return THREAD_GETMEM(self, p_tid); } +strong_alias (__pthread_self, pthread_self); -int pthread_equal(pthread_t thread1, pthread_t thread2) +int __pthread_equal(pthread_t thread1, pthread_t thread2) { return thread1 == thread2; } +strong_alias (__pthread_equal, pthread_equal); /* Helper function for thread_self in the case of user-provided stacks */ @@ -849,8 +839,8 @@ static pthread_descr thread_self_stack(void) /* Thread scheduling */ -int pthread_setschedparam(pthread_t thread, int policy, - const struct sched_param *param) +int __pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param) { pthread_handle handle = thread_handle(thread); pthread_descr th; @@ -872,9 +862,10 @@ int pthread_setschedparam(pthread_t thread, int policy, __pthread_manager_adjust_prio(th->p_priority); return 0; } +strong_alias (__pthread_setschedparam, pthread_setschedparam); -int pthread_getschedparam(pthread_t thread, int *policy, - struct sched_param *param) +int __pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param) { pthread_handle handle = thread_handle(thread); int pid, pol; @@ -892,6 +883,7 @@ int pthread_getschedparam(pthread_t thread, int *policy, *policy = pol; return 0; } +strong_alias (__pthread_getschedparam, pthread_getschedparam); int __pthread_yield (void) { @@ -1319,15 +1311,3 @@ void __pthread_message(const char * fmt, ...) } #endif - - -#ifndef SHARED -/* We need a hook to force the cancelation wrappers and file locking - to be linked in when static libpthread is used. */ -extern const int __pthread_provide_wrappers; -static const int *const __pthread_require_wrappers = - &__pthread_provide_wrappers; -extern const int __pthread_provide_lockfile; -static const int *const __pthread_require_lockfile = - &__pthread_provide_lockfile; -#endif diff --git a/linuxthreads/sysdeps/pthread/bits/libc-lock.h b/linuxthreads/sysdeps/pthread/bits/libc-lock.h index ceb08b6238..217b0be253 100644 --- a/linuxthreads/sysdeps/pthread/bits/libc-lock.h +++ b/linuxthreads/sysdeps/pthread/bits/libc-lock.h @@ -23,6 +23,10 @@ #include <pthread.h> +#if defined _LIBC && !defined NOT_IN_libc +#include <linuxthreads/internals.h> +#endif + /* Mutex type. */ #if defined(_LIBC) || defined(_IO_MTSAFE_IO) typedef pthread_mutex_t __libc_lock_t; @@ -90,19 +94,30 @@ typedef pthread_key_t __libc_key_t; #define _RTLD_LOCK_RECURSIVE_INITIALIZER \ {PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP} -#ifdef __PIC__ -# define __libc_maybe_call(FUNC, ARGS, ELSE) \ +#if defined _LIBC && defined IS_IN_libpthread +# define __libc_maybe_call(FUNC, ARGS, ELSE) FUNC ARGS +#else +# ifdef __PIC__ +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ (__extension__ ({ __typeof (FUNC) *_fn = (FUNC); \ _fn != NULL ? (*_fn) ARGS : ELSE; })) -#else -# define __libc_maybe_call(FUNC, ARGS, ELSE) \ +# else +# define __libc_maybe_call(FUNC, ARGS, ELSE) \ (FUNC != NULL ? FUNC ARGS : ELSE) +# endif +#endif +#if defined _LIBC && !defined NOT_IN_libc && defined __PIC__ +# define __libc_maybe_call2(FUNC, ARGS, ELSE) \ + ({__libc_pthread_functions.ptr_##FUNC != NULL \ + ? __libc_pthread_functions.ptr_##FUNC ARGS : ELSE; }) +#else +# define __libc_maybe_call2(FUNC, ARGS, ELSE) __libc_maybe_call (__##FUNC, ARGS, ELSE) #endif /* Initialize the named lock variable, leaving it in a consistent, unlocked state. */ #define __libc_lock_init(NAME) \ - (__libc_maybe_call (__pthread_mutex_init, (&(NAME), NULL), 0)) + (__libc_maybe_call2 (pthread_mutex_init, (&(NAME), NULL), 0)) #define __libc_rwlock_init(NAME) \ (__libc_maybe_call (__pthread_rwlock_init, (&(NAME), NULL), 0)); @@ -125,7 +140,7 @@ typedef pthread_key_t __libc_key_t; used again until __libc_lock_init is called again on it. This must be called on a lock variable before the containing storage is reused. */ #define __libc_lock_fini(NAME) \ - (__libc_maybe_call (__pthread_mutex_destroy, (&(NAME)), 0)); + (__libc_maybe_call2 (pthread_mutex_destroy, (&(NAME)), 0)); #define __libc_rwlock_fini(NAME) \ (__libc_maybe_call (__pthread_rwlock_destroy, (&(NAME)), 0)); @@ -135,7 +150,7 @@ typedef pthread_key_t __libc_key_t; /* Lock the named lock variable. */ #define __libc_lock_lock(NAME) \ - (__libc_maybe_call (__pthread_mutex_lock, (&(NAME)), 0)); + (__libc_maybe_call2 (pthread_mutex_lock, (&(NAME)), 0)); #define __libc_rwlock_rdlock(NAME) \ (__libc_maybe_call (__pthread_rwlock_rdlock, (&(NAME)), 0)); #define __libc_rwlock_wrlock(NAME) \ @@ -147,7 +162,7 @@ typedef pthread_key_t __libc_key_t; /* Try to lock the named lock variable. */ #define __libc_lock_trylock(NAME) \ - (__libc_maybe_call (__pthread_mutex_trylock, (&(NAME)), 0)) + (__libc_maybe_call2 (pthread_mutex_trylock, (&(NAME)), 0)) #define __libc_rwlock_tryrdlock(NAME) \ (__libc_maybe_call (__pthread_rwlock_tryrdlock, (&(NAME)), 0)) #define __libc_rwlock_trywrlock(NAME) \ @@ -160,7 +175,7 @@ typedef pthread_key_t __libc_key_t; /* Unlock the named lock variable. */ #define __libc_lock_unlock(NAME) \ - (__libc_maybe_call (__pthread_mutex_unlock, (&(NAME)), 0)); + (__libc_maybe_call2 (pthread_mutex_unlock, (&(NAME)), 0)); #define __libc_rwlock_unlock(NAME) \ (__libc_maybe_call (__pthread_rwlock_unlock, (&(NAME)), 0)); diff --git a/linuxthreads/sysdeps/pthread/flockfile.c b/linuxthreads/sysdeps/pthread/flockfile.c new file mode 100644 index 0000000000..a90215cc1f --- /dev/null +++ b/linuxthreads/sysdeps/pthread/flockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <stdio.h> +#include <libio.h> +#include <bits/stdio-lock.h> + + +void +__flockfile (stream) + FILE *stream; +{ + _IO_lock_lock (*stream->_lock); +} +strong_alias (__flockfile, _IO_flockfile) +strong_alias (__flockfile, flockfile) diff --git a/linuxthreads/sysdeps/pthread/ftrylockfile.c b/linuxthreads/sysdeps/pthread/ftrylockfile.c new file mode 100644 index 0000000000..21c1ea01ed --- /dev/null +++ b/linuxthreads/sysdeps/pthread/ftrylockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <errno.h> +#include <pthread.h> +#include <stdio.h> +#include <bits/stdio-lock.h> + + +int +__ftrylockfile (stream) + FILE *stream; +{ + return _IO_lock_trylock (*stream->_lock); +} +strong_alias (__ftrylockfile, _IO_ftrylockfile) +weak_alias (__ftrylockfile, ftrylockfile) diff --git a/linuxthreads/sysdeps/pthread/funlockfile.c b/linuxthreads/sysdeps/pthread/funlockfile.c new file mode 100644 index 0000000000..f941fc9851 --- /dev/null +++ b/linuxthreads/sysdeps/pthread/funlockfile.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <pthread.h> +#include <stdio.h> +#include <libio.h> +#include <bits/stdio-lock.h> + + +void +__funlockfile (stream) + FILE *stream; +{ + _IO_lock_unlock (*stream->_lock); +} +strong_alias (__funlockfile, _IO_funlockfile) +weak_alias (__funlockfile, funlockfile) diff --git a/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c b/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c new file mode 100644 index 0000000000..a18753233a --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/allocrtsig.c @@ -0,0 +1,85 @@ +/* Handle real-time signal allocation. + Copyright (C) 1997,98,99,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <signal.h> + +/* Sanity check. */ +#if !defined __SIGRTMIN || (__SIGRTMAX - __SIGRTMIN) < 3 +# error "This must not happen" +#endif + +static int current_rtmin; +static int current_rtmax; + +static int initialized; + +#include <testrtsig.h> + +static void +init (void) +{ + if (!kernel_has_rtsig ()) + { + current_rtmin = -1; + current_rtmax = -1; + } + else + { + current_rtmin = __SIGRTMIN + 3; + current_rtmax = __SIGRTMAX; + } + initialized = 1; +} + +/* Return number of available real-time signal with highest priority. */ +int +__libc_current_sigrtmin (void) +{ + if (!initialized) + init (); + return current_rtmin; +} +strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private); + +/* Return number of available real-time signal with lowest priority. */ +int +__libc_current_sigrtmax (void) +{ + if (!initialized) + init (); + return current_rtmax; +} +strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private); + +/* Allocate real-time signal with highest/lowest available + priority. Please note that we don't use a lock since we assume + this function to be called at program start. */ +int +__libc_allocate_rtsig (int high) +{ + if (!initialized) + init (); + if (current_rtmin == -1 || current_rtmin > current_rtmax) + /* We don't have anymore signal available. */ + return -1; + + return high ? current_rtmin++ : current_rtmax--; +} +strong_alias (__libc_allocate_rtsig, __libc_allocate_rtsig_private); diff --git a/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h new file mode 100644 index 0000000000..30be0b9c5f --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -0,0 +1,124 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#include <pt-machine.h> +#ifndef ASSEMBLER +# include <linuxthreads/internals.h> +#endif + +#if defined FLOATING_STACKS && USE___THREAD +# define MULTIPLE_THREADS_OFFSET 12 +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + CENABLE \ + SAVE_OLDTYPE_##args \ + PUSHARGS_##args \ + DOCARGS_##args \ + movl $SYS_ify (syscall_name), %eax; \ + int $0x80 \ + POPARGS_##args; \ + POPCARGS_##args \ + cmpl $-4095, %eax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define SAVE_OLDTYPE_0 movl %eax, %edx; +# define SAVE_OLDTYPE_1 SAVE_OLDTYPE_0 +# define SAVE_OLDTYPE_2 pushl %eax; +# define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 +# define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 + +# define DOCARGS_0 DOARGS_0 +# define DOCARGS_1 DOARGS_1 +# define DOCARGS_2 _DOARGS_2 (12) +# define DOCARGS_3 _DOARGS_3 (20) +# define DOCARGS_4 _DOARGS_4 (28) +# define DOCARGS_5 _DOARGS_5 (36) + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel +# else +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel +# endif +# define POPCARGS_0 pushl %eax; movl %ecx, %eax; CDISABLE; popl %eax; +# define POPCARGS_1 POPCARGS_0 +# define POPCARGS_2 xchgl (%esp), %eax; CDISABLE; popl %eax; +# define POPCARGS_3 POPCARGS_2 +# define POPCARGS_4 POPCARGS_2 +# define POPCARGS_5 POPCARGS_2 + +#if !defined NOT_IN_libc +# define __local_multiple_threads __libc_multiple_threads +#else +# define __local_multiple_threads __pthread_multiple_threads +#endif + +# ifndef ASSEMBLER +# if defined MULTIPLE_THREADS_OFFSET && defined PIC +# define SINGLE_THREAD_P \ + __builtin_expect (THREAD_GETMEM (THREAD_SELF, \ + p_header.data.multiple_threads) == 0, 1) +# else +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P __builtin_expect (__local_multiple_threads == 0, 1) +# endif +# else +# if !defined PIC +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads +# elif defined MULTIPLE_THREADS_OFFSET +# define SINGLE_THREAD_P cmpl $0, %gs:MULTIPLE_THREADS_OFFSET +# else +# if !defined HAVE_HIDDEN || !USE___THREAD +# define SINGLE_THREAD_P \ + SETUP_PIC_REG (cx); \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + cmpl $0, __local_multiple_threads@GOTOFF(%ecx) +# else +# define SINGLE_THREAD_P \ + call __i686.get_pc_thunk.cx; \ + addl $_GLOBAL_OFFSET_TABLE_, %ecx; \ + cmpl $0, __local_multiple_threads@GOTOFF(%ecx) +# endif +# endif +# endif + +#elif !defined ASSEMBLER + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h new file mode 100644 index 0000000000..1c7a95dcd8 --- /dev/null +++ b/linuxthreads/sysdeps/unix/sysv/linux/x86_64/sysdep-cancel.h @@ -0,0 +1,118 @@ +/* Copyright (C) 2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <sysdep.h> +#include <tls.h> +#include <pt-machine.h> +#ifndef ASSEMBLER +# include <linuxthreads/internals.h> +#endif + +#if !defined NOT_IN_libc || defined IS_IN_libpthread + +# undef PSEUDO +# define PSEUDO(name, syscall_name, args) \ + .text; \ + ENTRY (name) \ + SINGLE_THREAD_P; \ + jne L(pseudo_cancel); \ + DO_CALL (syscall_name, args); \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + ret; \ + L(pseudo_cancel): \ + SAVESTK_##args \ + PUSHARGS_##args \ + CENABLE \ + POPARGS_##args \ + movq %rax, OLDTYPE_##args; \ + movq $SYS_ify (syscall_name), %rax; \ + syscall; \ + xchgq %rax, OLDTYPE_##args; \ + CDISABLE \ + movq OLDTYPE_##args, %rax; \ + RESTSTK_##args \ + cmpq $-4095, %rax; \ + jae SYSCALL_ERROR_LABEL; \ + L(pseudo_end): + +# define PUSHARGS_0 /* Nothing. */ +# define PUSHARGS_1 PUSHARGS_0 movq %rdi, (%rsp); +# define PUSHARGS_2 PUSHARGS_1 movq %rsi, 8(%rsp); +# define PUSHARGS_3 PUSHARGS_2 movq %rdx, 16(%rsp); +# define PUSHARGS_4 PUSHARGS_3 movq %rcx, 24(%rsp); +# define PUSHARGS_5 PUSHARGS_4 movq %r8, 32(%rsp); +# define PUSHARGS_6 PUSHARGS_5 movq %r9, 40(%rsp); + +# define POPARGS_0 /* Nothing. */ +# define POPARGS_1 POPARGS_0 movq (%rsp), %rdi; +# define POPARGS_2 POPARGS_1 movq 8(%rsp), %rsi; +# define POPARGS_3 POPARGS_2 movq 16(%rsp), %rdx; +# define POPARGS_4 POPARGS_3 movq 24(%rsp), %r10; +# define POPARGS_5 POPARGS_4 movq 32(%rsp), %r8; +# define POPARGS_6 POPARGS_5 movq 40(%rsp), %r9; + +# define SAVESTK_0 /* Nothing. */ +# define SAVESTK_1 subq $16, %rsp; +# define SAVESTK_2 SAVESTK_1; +# define SAVESTK_3 subq $32, %rsp; +# define SAVESTK_4 SAVESTK_3; +# define SAVESTK_5 subq $48, %rsp; +# define SAVESTK_6 subq $64, %rsp; + +# define RESTSTK_0 /* Nothing. */ +# define RESTSTK_1 addq $16, %rsp; +# define RESTSTK_2 RESTSTK_1; +# define RESTSTK_3 addq $32, %rsp; +# define RESTSTK_4 RESTSTK_3; +# define RESTSTK_5 addq $48, %rsp; +# define RESTSTK_6 addq $64, %rsp; + +# define OLDTYPE_0 %r9 +# define OLDTYPE_1 OLDTYPE_0 +# define OLDTYPE_2 OLDTYPE_0 +# define OLDTYPE_3 OLDTYPE_0 +# define OLDTYPE_4 OLDTYPE_0 +# define OLDTYPE_5 OLDTYPE_0 +# define OLDTYPE_6 48(%rsp) + +# ifdef IS_IN_libpthread +# define CENABLE call __pthread_enable_asynccancel; +# define CDISABLE call __pthread_disable_asynccancel; +# define __local_multiple_threads __pthread_multiple_threads +# else +# define CENABLE call __libc_enable_asynccancel; +# define CDISABLE call __libc_disable_asynccancel; +# define __local_multiple_threads __libc_multiple_threads +# endif + +# ifndef ASSEMBLER +extern int __local_multiple_threads attribute_hidden; +# define SINGLE_THREAD_P \ + __builtin_expect (__local_multiple_threads == 0, 1) +# else +# define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip) +# endif + +#elif !defined ASSEMBLER + +/* This code should never be used but we define it anyhow. */ +# define SINGLE_THREAD_P (1) + +#endif diff --git a/linuxthreads/sysdeps/x86_64/pt-machine.h b/linuxthreads/sysdeps/x86_64/pt-machine.h index e0b68d315b..0a366c56eb 100644 --- a/linuxthreads/sysdeps/x86_64/pt-machine.h +++ b/linuxthreads/sysdeps/x86_64/pt-machine.h @@ -21,21 +21,22 @@ #ifndef _PT_MACHINE_H #define _PT_MACHINE_H 1 -#include <stddef.h> /* For offsetof. */ -#include <stdlib.h> /* For abort(). */ -#include <asm/prctl.h> +#ifndef __ASSEMBLER__ +# include <stddef.h> /* For offsetof. */ +# include <stdlib.h> /* For abort(). */ +# include <asm/prctl.h> -#ifndef PT_EI -# define PT_EI extern inline -#endif +# ifndef PT_EI +# define PT_EI extern inline +# endif extern long int testandset (int *spinlock); extern int __compare_and_swap (long int *p, long int oldval, long int newval); /* Get some notion of the current stack. Need not be exactly the top of the stack, just something somewhere in the current frame. */ -#define CURRENT_STACK_FRAME stack_pointer +# define CURRENT_STACK_FRAME stack_pointer register char * stack_pointer __asm__ ("%rsp"); @@ -56,7 +57,7 @@ testandset (int *spinlock) /* Compare-and-swap for semaphores. */ -#define HAS_COMPARE_AND_SWAP +# define HAS_COMPARE_AND_SWAP PT_EI int __compare_and_swap (long int *p, long int oldval, long int newval) @@ -77,7 +78,7 @@ __compare_and_swap (long int *p, long int oldval, long int newval) assignments like pthread_descr self = thread_self(); do not get optimized away. */ -#define THREAD_SELF \ +# define THREAD_SELF \ ({ \ register pthread_descr __self; \ __asm__ ("movq %%fs:%c1,%0" : "=r" (__self) \ @@ -90,14 +91,14 @@ __compare_and_swap (long int *p, long int oldval, long int newval) extern int __arch_prctl (int __code, unsigned long __addr); /* Initialize the thread-unique value. */ -#define INIT_THREAD_SELF(descr, nr) \ +# define INIT_THREAD_SELF(descr, nr) \ { \ if (__arch_prctl (ARCH_SET_FS, (unsigned long)descr) != 0) \ abort (); \ } /* Read member of the thread descriptor directly. */ -#define THREAD_GETMEM(descr, member) \ +# define THREAD_GETMEM(descr, member) \ ({ \ __typeof__ (descr->member) __value; \ if (sizeof (__value) == 1) \ @@ -127,7 +128,7 @@ extern int __arch_prctl (int __code, unsigned long __addr); }) /* Same as THREAD_GETMEM, but the member offset can be non-constant. */ -#define THREAD_GETMEM_NC(descr, member) \ +# define THREAD_GETMEM_NC(descr, member) \ ({ \ __typeof__ (descr->member) __value; \ if (sizeof (__value) == 1) \ @@ -157,7 +158,7 @@ extern int __arch_prctl (int __code, unsigned long __addr); }) /* Set member of the thread descriptor directly. */ -#define THREAD_SETMEM(descr, member, value) \ +# define THREAD_SETMEM(descr, member, value) \ ({ \ __typeof__ (descr->member) __value = (value); \ if (sizeof (__value) == 1) \ @@ -184,7 +185,7 @@ extern int __arch_prctl (int __code, unsigned long __addr); }) /* Same as THREAD_SETMEM, but the member offset can be non-constant. */ -#define THREAD_SETMEM_NC(descr, member, value) \ +# define THREAD_SETMEM_NC(descr, member, value) \ ({ \ __typeof__ (descr->member) __value = (value); \ if (sizeof (__value) == 1) \ @@ -210,6 +211,8 @@ extern int __arch_prctl (int __code, unsigned long __addr); } \ }) +#endif /* !__ASSEMBLER__ */ + /* We want the OS to assign stack addresses. */ #define FLOATING_STACKS 1 diff --git a/linuxthreads/tst-cancel-wrappers.sh b/linuxthreads/tst-cancel-wrappers.sh new file mode 100644 index 0000000000..14c42dfb8b --- /dev/null +++ b/linuxthreads/tst-cancel-wrappers.sh @@ -0,0 +1,96 @@ +#! /bin/sh +# Test whether all cancellable functions are cancellable. +# Copyright (C) 2002 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# Contributed by Jakub Jelinek <jakub@redhat.com>, 2002. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, write to the Free +# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA +# 02111-1307 USA. + +while [ $# -gt 0 ]; do + ( nm -P $1; echo 'end[end]:' ) | awk ' BEGIN { +C["accept"]=1 +C["close"]=1 +C["connect"]=1 +C["creat"]=1 +C["fcntl"]=1 +C["fsync"]=1 +C["llseek"]=1 +C["lseek"]=1 +C["msgrcv"]=1 +C["msgsnd"]=1 +C["msync"]=1 +C["nanosleep"]=1 +C["open"]=1 +C["open64"]=1 +C["pause"]=1 +C["poll"]=1 +C["pread"]=1 +C["pread64"]=1 +C["pselect"]=1 +C["pwrite"]=1 +C["pwrite64"]=1 +C["read"]=1 +C["readv"]=1 +C["recv"]=1 +C["recvfrom"]=1 +C["recvmsg"]=1 +C["select"]=1 +C["send"]=1 +C["sendmsg"]=1 +C["sendto"]=1 +C["sigpause"]=1 +C["sigsuspend"]=1 +C["sigwait"]=1 +C["sigwaitinfo"]=1 +C["system"]=1 +C["tcdrain"]=1 +C["wait"]=1 +C["waitid"]=1 +C["waitpid"]=1 +C["write"]=1 +C["writev"]=1 +C["__xpg_sigpause"]=1 +} +/:$/ { + if (seen) + { + # signals.c in linuxthreads does the cancellation checks not using + # *_{enable,disable}_asynccancel. + if ((!seen_enable || !seen_disable) && !(object ~ /^signals.o/)) + { + printf "in '$1'(%s) %s'\''s cancellation missing\n", object, seen + ret = 1 + } + } + seen="" + seen_enable="" + seen_disable="" + object=gensub(/^.*\[(.*)\]:$/,"\\1","",$0) + next +} +{ + if (C[$1] && $2 ~ /^[TW]$/) + seen=$1 + else if ($1 ~ /^__(libc|pthread)_enable_asynccancel$/ && $2 == "U") + seen_enable=1 + else if ($1 ~ /^__(libc|pthread)_disable_asynccancel$/ && $2 == "U") + seen_disable=1 +} +END { + exit ret +}' || exit + shift +done diff --git a/linuxthreads/weaks.c b/linuxthreads/weaks.c deleted file mode 100644 index cd17e6804b..0000000000 --- a/linuxthreads/weaks.c +++ /dev/null @@ -1,97 +0,0 @@ -/* The weak pthread functions for Linux. - Copyright (C) 1996,97,98,99,2000,01,02 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include <limits.h> -#include <stdlib.h> -#include <shlib-compat.h> -#include <bp-sym.h> - -extern int __pthread_return_0 (void); -extern int __pthread_return_1 (void); -extern void __pthread_return_void (void); -extern void weak_function pthread_exit (void *__retval) - __attribute__ ((noreturn)); - -/* Those are pthread functions which return 0 if successful. */ -weak_alias (__pthread_return_0, BP_SYM (__libc_pthread_attr_init_2_1)) -versioned_symbol (libpthread, BP_SYM (__libc_pthread_attr_init_2_1), - BP_SYM (pthread_attr_init), GLIBC_2_1); -#if SHLIB_COMPAT(libpthread, GLIBC_2_0, GLIBC_2_1) -weak_alias (__pthread_return_0, BP_SYM (__libc_pthread_attr_init_2_0)) -compat_symbol (libpthread, BP_SYM (__libc_pthread_attr_init_2_0), - BP_SYM (pthread_attr_init), GLIBC_2_0); -#endif -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_destroy)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setdetachstate)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getdetachstate)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setschedparam)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getschedparam)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setschedpolicy)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getschedpolicy)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setinheritsched)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getinheritsched)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setscope)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_getscope)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setstackaddr)) -weak_alias (__pthread_return_0, BP_SYM (pthread_attr_setstacksize)) -weak_alias (__pthread_return_0, BP_SYM (pthread_mutex_init)) -weak_alias (__pthread_return_0, BP_SYM (pthread_mutex_destroy)) -weak_alias (__pthread_return_0, BP_SYM (pthread_mutex_lock)) -weak_alias (__pthread_return_0, BP_SYM (pthread_mutex_unlock)) -weak_alias (__pthread_return_0, BP_SYM (pthread_condattr_init)) -weak_alias (__pthread_return_0, BP_SYM (pthread_condattr_destroy)) -weak_alias (__pthread_return_0, BP_SYM (pthread_setschedparam)) -weak_alias (__pthread_return_0, BP_SYM (pthread_getschedparam)) -weak_alias (__pthread_return_0, BP_SYM (pthread_setcancelstate)) -weak_alias (__pthread_return_0, BP_SYM (pthread_setcanceltype)) -weak_alias (__pthread_return_0, pthread_self) -weak_alias (__pthread_return_0, BP_SYM (pthread_cond_init)) -weak_alias (__pthread_return_0, BP_SYM (pthread_cond_destroy)) -weak_alias (__pthread_return_0, BP_SYM (pthread_cond_wait)) -weak_alias (__pthread_return_0, BP_SYM (pthread_cond_signal)) -weak_alias (__pthread_return_0, BP_SYM (pthread_cond_broadcast)) - - -/* Those are pthread functions which return 1 if successful. */ -weak_alias (__pthread_return_1, pthread_equal) - -/* pthread_exit () is a special case. */ -void -weak_function -pthread_exit (void *retval) -{ - exit (EXIT_SUCCESS); -} - -int -__pthread_return_0 (void) -{ - return 0; -} - -int -__pthread_return_1 (void) -{ - return 1; -} - -void -__pthread_return_void (void) -{ -} diff --git a/linuxthreads/wrapsyscall.c b/linuxthreads/wrapsyscall.c deleted file mode 100644 index 1a9436bd84..0000000000 --- a/linuxthreads/wrapsyscall.c +++ /dev/null @@ -1,233 +0,0 @@ -/* Wrapper arpund system calls to provide cancelation points. - Copyright (C) 1996-1999,2000-2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include <fcntl.h> -#include <sys/mman.h> -#include <pthread.h> -#include <unistd.h> -#include <stdarg.h> -#include <stddef.h> -#include <stdlib.h> -#include <termios.h> -#include <sys/poll.h> -#include <sys/resource.h> -#include <sys/select.h> -#include <sys/uio.h> -#include <sys/wait.h> -#include <sys/socket.h> - - -#ifndef SHARED -/* We need a hook to force this file to be linked in when static - libpthread is used. */ -const int __pthread_provide_wrappers = 0; -#endif - - -#define CANCELABLE_SYSCALL(res_type, name, param_list, params) \ -extern res_type __libc_##name param_list; \ -res_type \ -name param_list \ -{ \ - res_type result; \ - int oldtype; \ - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ - result = __libc_##name params; \ - pthread_setcanceltype (oldtype, NULL); \ - return result; \ -} - -#define CANCELABLE_SYSCALL_VA(res_type, name, param_list, params, last_arg) \ -res_type __libc_##name param_list; \ -res_type \ -name param_list \ -{ \ - res_type result; \ - int oldtype; \ - va_list ap; \ - pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype); \ - va_start (ap, last_arg); \ - result = __libc_##name params; \ - va_end (ap); \ - pthread_setcanceltype (oldtype, NULL); \ - return result; \ -} - -#define PROMOTE_INTEGRAL_TYPE(type) __typeof__ ((type) 0 + 0) - - -/* close(2). */ -CANCELABLE_SYSCALL (int, close, (int fd), (fd)) -strong_alias (close, __close) - - -/* fcntl(2). */ -CANCELABLE_SYSCALL_VA (int, fcntl, (int fd, int cmd, ...), - (fd, cmd, va_arg (ap, long int)), cmd) -strong_alias (fcntl, __fcntl) - - -/* fsync(2). */ -CANCELABLE_SYSCALL (int, fsync, (int fd), (fd)) - - -/* lseek(2). */ -CANCELABLE_SYSCALL (off_t, lseek, (int fd, off_t offset, int whence), - (fd, offset, whence)) -strong_alias (lseek, __lseek) - - -/* lseek64(2). */ -CANCELABLE_SYSCALL (off64_t, lseek64, (int fd, off64_t offset, int whence), - (fd, offset, whence)) - - -/* msync(2). */ -CANCELABLE_SYSCALL (int, msync, (__ptr_t addr, size_t length, int flags), - (addr, length, flags)) - - -/* nanosleep(2). */ -CANCELABLE_SYSCALL (int, nanosleep, (const struct timespec *requested_time, - struct timespec *remaining), - (requested_time, remaining)) -strong_alias (nanosleep, __nanosleep) - - -/* open(2). */ -CANCELABLE_SYSCALL_VA (int, open, (const char *pathname, int flags, ...), - (pathname, flags, - va_arg (ap, PROMOTE_INTEGRAL_TYPE (mode_t))), - flags) -strong_alias (open, __open) - - -/* open64(3). */ -CANCELABLE_SYSCALL_VA (int, open64, (const char *pathname, int flags, ...), - (pathname, flags, - va_arg (ap, PROMOTE_INTEGRAL_TYPE (mode_t))), - flags) -strong_alias (open64, __open64) - - -/* pause(2). */ -CANCELABLE_SYSCALL (int, pause, (void), ()) - - -/* pread(3). */ -CANCELABLE_SYSCALL (ssize_t, pread, (int fd, void *buf, size_t count, - off_t offset), - (fd, buf, count, offset)) - - -/* pread64(3). */ -CANCELABLE_SYSCALL (ssize_t, pread64, (int fd, void *buf, size_t count, - off64_t offset), - (fd, buf, count, offset)) -strong_alias (pread64, __pread64) - - -/* pwrite(3). */ -CANCELABLE_SYSCALL (ssize_t, pwrite, (int fd, const void *buf, size_t n, - off_t offset), - (fd, buf, n, offset)) - - -/* pwrite64(3). */ -CANCELABLE_SYSCALL (ssize_t, pwrite64, (int fd, const void *buf, size_t n, - off64_t offset), - (fd, buf, n, offset)) -strong_alias (pwrite64, __pwrite64) - - -/* read(2). */ -CANCELABLE_SYSCALL (ssize_t, read, (int fd, void *buf, size_t count), - (fd, buf, count)) -strong_alias (read, __read) - - -/* system(3). */ -CANCELABLE_SYSCALL (int, system, (const char *line), (line)) - - -/* tcdrain(2). */ -CANCELABLE_SYSCALL (int, tcdrain, (int fd), (fd)) - - -/* wait(2). */ -CANCELABLE_SYSCALL (__pid_t, wait, (__WAIT_STATUS_DEFN stat_loc), (stat_loc)) -strong_alias (wait, __wait) - - -/* waitpid(2). */ -CANCELABLE_SYSCALL (__pid_t, waitpid, (__pid_t pid, int *stat_loc, - int options), - (pid, stat_loc, options)) - - -/* write(2). */ -CANCELABLE_SYSCALL (ssize_t, write, (int fd, const void *buf, size_t n), - (fd, buf, n)) -strong_alias (write, __write) - - -/* The following system calls are thread cancellation points specified - in XNS. */ - -/* accept(2). */ -CANCELABLE_SYSCALL (int, accept, (int fd, __SOCKADDR_ARG addr, - socklen_t *addr_len), - (fd, addr, addr_len)) - -/* connect(2). */ -CANCELABLE_SYSCALL (int, connect, (int fd, __CONST_SOCKADDR_ARG addr, - socklen_t len), - (fd, addr, len)) -strong_alias (connect, __connect) - -/* recv(2). */ -CANCELABLE_SYSCALL (ssize_t, recv, (int fd, __ptr_t buf, size_t n, int flags), - (fd, buf, n, flags)) - -/* recvfrom(2). */ -CANCELABLE_SYSCALL (ssize_t, recvfrom, (int fd, __ptr_t buf, size_t n, int flags, - __SOCKADDR_ARG addr, socklen_t *addr_len), - (fd, buf, n, flags, addr, addr_len)) - -/* recvmsg(2). */ -CANCELABLE_SYSCALL (ssize_t, recvmsg, (int fd, struct msghdr *message, int flags), - (fd, message, flags)) - -/* send(2). */ -CANCELABLE_SYSCALL (ssize_t, send, (int fd, const __ptr_t buf, size_t n, - int flags), - (fd, buf, n, flags)) -strong_alias (send, __send) - -/* sendmsg(2). */ -CANCELABLE_SYSCALL (ssize_t, sendmsg, (int fd, const struct msghdr *message, - int flags), - (fd, message, flags)) - -/* sendto(2). */ -CANCELABLE_SYSCALL (ssize_t, sendto, (int fd, const __ptr_t buf, size_t n, - int flags, __CONST_SOCKADDR_ARG addr, - socklen_t addr_len), - (fd, buf, n, flags, addr, addr_len)) diff --git a/sysdeps/unix/sysv/linux/alpha/syscalls.list b/sysdeps/unix/sysv/linux/alpha/syscalls.list index 7f5c9d0052..6907ef1d2f 100644 --- a/sysdeps/unix/sysv/linux/alpha/syscalls.list +++ b/sysdeps/unix/sysv/linux/alpha/syscalls.list @@ -2,8 +2,8 @@ oldmsgctl EXTRA msgctl 3 __old_msgctl msgctl@GLIBC_2.0 msgget - msgget 2 __msgget msgget -msgrcv - msgrcv 5 __msgrcv msgrcv -msgsnd - msgsnd 4 __msgsnd msgsnd +msgrcv - msgrcv C:5 __msgrcv msgrcv +msgsnd - msgsnd C:4 __msgsnd msgsnd shmat - osf_shmat 3 __shmat shmat oldshmctl EXTRA shmctl 3 __old_shmctl shmctl@GLIBC_2.0 shmdt - shmdt 1 __shmdt shmdt diff --git a/sysdeps/unix/sysv/linux/hppa/syscalls.list b/sysdeps/unix/sysv/linux/hppa/syscalls.list index 6edb2d2b16..bc977e2e30 100644 --- a/sysdeps/unix/sysv/linux/hppa/syscalls.list +++ b/sysdeps/unix/sysv/linux/hppa/syscalls.list @@ -3,8 +3,8 @@ # semaphore and shm system calls msgctl - msgctl i:iip __msgctl msgctl msgget - msgget i:ii __msgget msgget -msgrcv - msgrcv i:ibnii __msgrcv msgrcv -msgsnd - msgsnd i:ibni __msgsnd msgsnd +msgrcv - msgrcv Ci:ibnii __msgrcv msgrcv +msgsnd - msgsnd Ci:ibni __msgsnd msgsnd shmat - shmat i:ipi __shmat shmat shmctl - shmctl i:iip __shmctl shmctl shmdt - shmdt i:s __shmdt shmdt diff --git a/sysdeps/unix/sysv/linux/ia64/sigsuspend.c b/sysdeps/unix/sysv/linux/ia64/sigsuspend.c index a0023acb7f..5accdda05f 100644 --- a/sysdeps/unix/sysv/linux/ia64/sigsuspend.c +++ b/sysdeps/unix/sysv/linux/ia64/sigsuspend.c @@ -20,7 +20,7 @@ #include <signal.h> #include <unistd.h> -#include <sysdep.h> +#include <sysdep-cancel.h> #include <sys/syscall.h> #include <bp-checks.h> @@ -35,7 +35,16 @@ __sigsuspend (set) { /* XXX The size argument hopefully will have to be changed to the real size of the user-level sigset_t. */ - return INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set), _NSIG / 8); + if (SINGLE_THREAD_P) + return INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set), _NSIG / 8); + + int oldtype = LIBC_CANCEL_ASYNC (); + + int result = INLINE_SYSCALL (rt_sigsuspend, 2, CHECK_SIGSET (set), _NSIG / 8); + + LIBC_CANCEL_RESET (oldtype); + + return result; } libc_hidden_def (__sigsuspend) weak_alias (__sigsuspend, sigsuspend) diff --git a/sysdeps/unix/sysv/linux/ia64/syscalls.list b/sysdeps/unix/sysv/linux/ia64/syscalls.list index 7c0f11f668..7df0265feb 100644 --- a/sysdeps/unix/sysv/linux/ia64/syscalls.list +++ b/sysdeps/unix/sysv/linux/ia64/syscalls.list @@ -22,8 +22,8 @@ sendfile - sendfile i:iipi sendfile sendfile64 # semaphore and shm system calls msgctl - msgctl i:iip __msgctl msgctl msgget - msgget i:ii __msgget msgget -msgrcv - msgrcv i:ibnii __msgrcv msgrcv -msgsnd - msgsnd i:ibni __msgsnd msgsnd +msgrcv - msgrcv Ci:ibnii __msgrcv msgrcv +msgsnd - msgsnd Ci:ibni __msgsnd msgsnd shmat - shmat i:ipi __shmat shmat shmctl - shmctl i:iip __shmctl shmctl shmdt - shmdt i:s __shmdt shmdt diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list b/sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list index 55c8c3aa8e..d813d7af51 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list +++ b/sysdeps/unix/sysv/linux/s390/s390-64/syscalls.list @@ -15,8 +15,8 @@ setrlimit - setrlimit 2 __setrlimit setrlimit setrlimit64 # semaphore and shm system calls msgctl - msgctl i:iip __msgctl msgctl msgget - msgget i:ii __msgget msgget -msgrcv - msgrcv i:ibnii __msgrcv msgrcv -msgsnd - msgsnd i:ibni __msgsnd msgsnd +msgrcv - msgrcv Ci:ibnii __msgrcv msgrcv +msgsnd - msgsnd Ci:ibni __msgsnd msgsnd shmat - shmat i:ipi __shmat shmat shmctl - shmctl i:iip __shmctl shmctl shmdt - shmdt i:s __shmdt shmdt diff --git a/sysdeps/unix/sysv/linux/x86_64/syscalls.list b/sysdeps/unix/sysv/linux/x86_64/syscalls.list index a5c1288f61..64abc4fc74 100644 --- a/sysdeps/unix/sysv/linux/x86_64/syscalls.list +++ b/sysdeps/unix/sysv/linux/x86_64/syscalls.list @@ -18,8 +18,8 @@ sendfile - sendfile i:iipi sendfile sendfile64 # semaphore and shm system calls msgctl - msgctl i:iip __msgctl msgctl msgget - msgget i:ii __msgget msgget -msgrcv - msgrcv i:ibnii __msgrcv msgrcv -msgsnd - msgsnd i:ibni __msgsnd msgsnd +msgrcv - msgrcv Ci:ibnii __msgrcv msgrcv +msgsnd - msgsnd Ci:ibni __msgsnd msgsnd shmat - shmat i:ipi __shmat shmat shmctl - shmctl i:iip __shmctl shmctl shmdt - shmdt i:s __shmdt shmdt |