From 08192659bbeae149e7cb1f4c43547257f7099bb0 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Mon, 7 Jul 2014 09:28:38 -0700 Subject: Get rid of nptl/sysdeps/ entirely! --- ChangeLog | 147 ++++++++++ nptl/Makefile | 13 +- nptl/Versions | 5 + nptl/internaltypes.h | 161 +++++++++++ nptl/libc-lowlevellock.c | 20 ++ nptl/libc_multiple_threads.c | 28 ++ nptl/libc_pthread_init.c | 86 ++++++ nptl/lowlevelbarrier.sym | 12 + nptl/lowlevelcond.sym | 16 ++ nptl/lowlevellock.c | 124 ++++++++ nptl/lowlevellock.h | 83 ------ nptl/lowlevelrobustlock.c | 128 +++++++++ nptl/lowlevelrobustlock.sym | 6 + nptl/lowlevelrwlock.sym | 16 ++ nptl/pt-fork.c | 27 ++ nptl/pthread-pi-defines.sym | 9 + nptl/pthread_attr_getaffinity.c | 74 +++++ nptl/pthread_attr_setaffinity.c | 80 ++++++ nptl/pthread_mutex_cond_lock.c | 21 ++ nptl/pthread_once.c | 109 +++++-- nptl/pthread_yield.c | 29 ++ nptl/register-atfork.c | 145 ++++++++++ nptl/sem_post.c | 80 ++++++ nptl/sem_timedwait.c | 116 ++++++++ nptl/sem_trywait.c | 50 ++++ nptl/sem_wait.c | 123 ++++++++ nptl/structsem.sym | 12 + nptl/sysdeps/unix/sysv/linux/Makefile | 39 --- nptl/sysdeps/unix/sysv/linux/Versions | 15 - nptl/sysdeps/unix/sysv/linux/aio_misc.h | 68 ----- nptl/sysdeps/unix/sysv/linux/allocrtsig.c | 55 ---- nptl/sysdeps/unix/sysv/linux/createthread.c | 23 -- nptl/sysdeps/unix/sysv/linux/fork.c | 238 ---------------- nptl/sysdeps/unix/sysv/linux/fork.h | 59 ---- nptl/sysdeps/unix/sysv/linux/getpid.c | 64 ----- nptl/sysdeps/unix/sysv/linux/internaltypes.h | 161 ----------- nptl/sysdeps/unix/sysv/linux/jmp-unwind.c | 38 --- nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h | 67 ----- nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c | 20 -- .../unix/sysv/linux/libc_multiple_threads.c | 28 -- nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c | 86 ------ nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym | 12 - nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym | 16 -- nptl/sysdeps/unix/sysv/linux/lowlevellock.c | 124 -------- nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c | 128 --------- .../sysdeps/unix/sysv/linux/lowlevelrobustlock.sym | 6 - nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym | 16 -- nptl/sysdeps/unix/sysv/linux/mq_notify.c | 282 ------------------ nptl/sysdeps/unix/sysv/linux/pt-fork.c | 27 -- nptl/sysdeps/unix/sysv/linux/pt-raise.c | 38 --- .../sysdeps/unix/sysv/linux/pthread-pi-defines.sym | 9 - .../unix/sysv/linux/pthread_attr_getaffinity.c | 74 ----- .../unix/sysv/linux/pthread_attr_setaffinity.c | 80 ------ nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c | 59 ---- .../unix/sysv/linux/pthread_getcpuclockid.c | 44 --- nptl/sysdeps/unix/sysv/linux/pthread_getname.c | 72 ----- nptl/sysdeps/unix/sysv/linux/pthread_kill.c | 66 ----- .../unix/sysv/linux/pthread_mutex_cond_lock.c | 21 -- nptl/sysdeps/unix/sysv/linux/pthread_once.c | 131 --------- nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c | 104 ------- nptl/sysdeps/unix/sysv/linux/pthread_setname.c | 65 ----- nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c | 81 ------ nptl/sysdeps/unix/sysv/linux/pthread_yield.c | 29 -- nptl/sysdeps/unix/sysv/linux/raise.c | 58 ---- nptl/sysdeps/unix/sysv/linux/register-atfork.c | 145 ---------- nptl/sysdeps/unix/sysv/linux/sem_post.c | 80 ------ nptl/sysdeps/unix/sysv/linux/sem_timedwait.c | 116 -------- nptl/sysdeps/unix/sysv/linux/sem_trywait.c | 50 ---- nptl/sysdeps/unix/sysv/linux/sem_wait.c | 123 -------- nptl/sysdeps/unix/sysv/linux/sigtimedwait.c | 2 - nptl/sysdeps/unix/sysv/linux/sigwait.c | 2 - nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c | 2 - nptl/sysdeps/unix/sysv/linux/sleep.c | 10 - nptl/sysdeps/unix/sysv/linux/structsem.sym | 12 - nptl/sysdeps/unix/sysv/linux/timer_create.c | 179 ------------ nptl/sysdeps/unix/sysv/linux/timer_delete.c | 73 ----- nptl/sysdeps/unix/sysv/linux/timer_getoverr.c | 41 --- nptl/sysdeps/unix/sysv/linux/timer_gettime.c | 43 --- nptl/sysdeps/unix/sysv/linux/timer_routines.c | 196 ------------- nptl/sysdeps/unix/sysv/linux/timer_settime.c | 46 --- nptl/sysdeps/unix/sysv/linux/tst-setgetname.c | 315 --------------------- nptl/sysdeps/unix/sysv/linux/unregister-atfork.c | 121 -------- nptl/sysdeps/unix/sysv/linux/unwindbuf.sym | 7 - nptl/unregister-atfork.c | 121 ++++++++ nptl/unwindbuf.sym | 7 + sysdeps/nptl/fork.c | 238 ++++++++++++++++ sysdeps/nptl/fork.h | 59 ++++ sysdeps/nptl/jmp-unwind.c | 38 +++ sysdeps/nptl/lowlevellock.h | 83 ++++++ sysdeps/sparc/sparc32/sparcv9/sem_trywait.c | 2 +- sysdeps/unix/sysv/linux/Makefile | 8 + sysdeps/unix/sysv/linux/aarch64/sigaction.c | 10 +- sysdeps/unix/sysv/linux/aio_misc.h | 68 +++++ sysdeps/unix/sysv/linux/allocrtsig.c | 55 ++++ sysdeps/unix/sysv/linux/alpha/sem_post.c | 2 +- sysdeps/unix/sysv/linux/arm/sigaction.c | 10 +- sysdeps/unix/sysv/linux/getpid.c | 64 +++++ sysdeps/unix/sysv/linux/i386/sigaction.c | 10 +- sysdeps/unix/sysv/linux/ia64/fork.S | 40 --- sysdeps/unix/sysv/linux/ia64/sigaction.c | 10 +- sysdeps/unix/sysv/linux/kernel-posix-timers.h | 67 +++++ sysdeps/unix/sysv/linux/mips/sigaction.c | 9 +- sysdeps/unix/sysv/linux/mq_notify.c | 251 +++++++++++++++- sysdeps/unix/sysv/linux/pt-raise.c | 38 +++ sysdeps/unix/sysv/linux/pthread_getaffinity.c | 59 ++++ sysdeps/unix/sysv/linux/pthread_getcpuclockid.c | 44 +++ sysdeps/unix/sysv/linux/pthread_getname.c | 72 +++++ sysdeps/unix/sysv/linux/pthread_kill.c | 66 +++++ sysdeps/unix/sysv/linux/pthread_setaffinity.c | 104 +++++++ sysdeps/unix/sysv/linux/pthread_setname.c | 65 +++++ sysdeps/unix/sysv/linux/pthread_sigqueue.c | 81 ++++++ sysdeps/unix/sysv/linux/raise.c | 58 ++++ sysdeps/unix/sysv/linux/s390/jmp-unwind.c | 2 +- .../unix/sysv/linux/s390/pthread_mutex_cond_lock.c | 2 +- sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c | 10 +- sysdeps/unix/sysv/linux/sigaction.c | 10 +- sysdeps/unix/sysv/linux/sigtimedwait.c | 1 + sysdeps/unix/sysv/linux/sigwait.c | 1 + sysdeps/unix/sysv/linux/sigwaitinfo.c | 1 + sysdeps/unix/sysv/linux/sleep.c | 1 + sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c | 9 +- sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c | 9 +- sysdeps/unix/sysv/linux/syscalls.list | 1 - sysdeps/unix/sysv/linux/timer_create.c | 179 ++++++++++++ sysdeps/unix/sysv/linux/timer_delete.c | 73 +++++ sysdeps/unix/sysv/linux/timer_getoverr.c | 41 +++ sysdeps/unix/sysv/linux/timer_gettime.c | 43 +++ sysdeps/unix/sysv/linux/timer_routines.c | 196 +++++++++++++ sysdeps/unix/sysv/linux/timer_settime.c | 46 +++ sysdeps/unix/sysv/linux/tst-setgetname.c | 315 +++++++++++++++++++++ .../unix/sysv/linux/x86/pthread_mutex_cond_lock.c | 2 +- sysdeps/unix/sysv/linux/x86_64/sigaction.c | 11 +- 132 files changed, 4171 insertions(+), 4307 deletions(-) create mode 100644 nptl/internaltypes.h create mode 100644 nptl/libc-lowlevellock.c create mode 100644 nptl/libc_multiple_threads.c create mode 100644 nptl/libc_pthread_init.c create mode 100644 nptl/lowlevelbarrier.sym create mode 100644 nptl/lowlevelcond.sym create mode 100644 nptl/lowlevellock.c delete mode 100644 nptl/lowlevellock.h create mode 100644 nptl/lowlevelrobustlock.c create mode 100644 nptl/lowlevelrobustlock.sym create mode 100644 nptl/lowlevelrwlock.sym create mode 100644 nptl/pt-fork.c create mode 100644 nptl/pthread-pi-defines.sym create mode 100644 nptl/pthread_attr_getaffinity.c create mode 100644 nptl/pthread_attr_setaffinity.c create mode 100644 nptl/pthread_mutex_cond_lock.c create mode 100644 nptl/pthread_yield.c create mode 100644 nptl/register-atfork.c create mode 100644 nptl/sem_post.c create mode 100644 nptl/sem_timedwait.c create mode 100644 nptl/sem_trywait.c create mode 100644 nptl/sem_wait.c create mode 100644 nptl/structsem.sym delete mode 100644 nptl/sysdeps/unix/sysv/linux/Makefile delete mode 100644 nptl/sysdeps/unix/sysv/linux/Versions delete mode 100644 nptl/sysdeps/unix/sysv/linux/aio_misc.h delete mode 100644 nptl/sysdeps/unix/sysv/linux/allocrtsig.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/createthread.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/fork.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/fork.h delete mode 100644 nptl/sysdeps/unix/sysv/linux/getpid.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/internaltypes.h delete mode 100644 nptl/sysdeps/unix/sysv/linux/jmp-unwind.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h delete mode 100644 nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym delete mode 100644 nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym delete mode 100644 nptl/sysdeps/unix/sysv/linux/lowlevellock.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym delete mode 100644 nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym delete mode 100644 nptl/sysdeps/unix/sysv/linux/mq_notify.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pt-fork.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pt-raise.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_getname.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_kill.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_once.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_setname.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/pthread_yield.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/raise.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/register-atfork.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/sem_post.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/sem_timedwait.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/sem_trywait.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/sem_wait.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/sigtimedwait.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/sigwait.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/sleep.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/structsem.sym delete mode 100644 nptl/sysdeps/unix/sysv/linux/timer_create.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/timer_delete.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/timer_getoverr.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/timer_gettime.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/timer_routines.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/timer_settime.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/tst-setgetname.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/unregister-atfork.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/unwindbuf.sym create mode 100644 nptl/unregister-atfork.c create mode 100644 nptl/unwindbuf.sym create mode 100644 sysdeps/nptl/fork.c create mode 100644 sysdeps/nptl/fork.h create mode 100644 sysdeps/nptl/jmp-unwind.c create mode 100644 sysdeps/nptl/lowlevellock.h create mode 100644 sysdeps/unix/sysv/linux/aio_misc.h create mode 100644 sysdeps/unix/sysv/linux/allocrtsig.c create mode 100644 sysdeps/unix/sysv/linux/getpid.c delete mode 100644 sysdeps/unix/sysv/linux/ia64/fork.S create mode 100644 sysdeps/unix/sysv/linux/kernel-posix-timers.h create mode 100644 sysdeps/unix/sysv/linux/pt-raise.c create mode 100644 sysdeps/unix/sysv/linux/pthread_getaffinity.c create mode 100644 sysdeps/unix/sysv/linux/pthread_getcpuclockid.c create mode 100644 sysdeps/unix/sysv/linux/pthread_getname.c create mode 100644 sysdeps/unix/sysv/linux/pthread_kill.c create mode 100644 sysdeps/unix/sysv/linux/pthread_setaffinity.c create mode 100644 sysdeps/unix/sysv/linux/pthread_setname.c create mode 100644 sysdeps/unix/sysv/linux/pthread_sigqueue.c create mode 100644 sysdeps/unix/sysv/linux/raise.c create mode 100644 sysdeps/unix/sysv/linux/timer_create.c create mode 100644 sysdeps/unix/sysv/linux/timer_delete.c create mode 100644 sysdeps/unix/sysv/linux/timer_getoverr.c create mode 100644 sysdeps/unix/sysv/linux/timer_gettime.c create mode 100644 sysdeps/unix/sysv/linux/timer_routines.c create mode 100644 sysdeps/unix/sysv/linux/timer_settime.c create mode 100644 sysdeps/unix/sysv/linux/tst-setgetname.c diff --git a/ChangeLog b/ChangeLog index d5458c7030..39f0e78837 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,150 @@ +2014-07-07 Roland McGrath + + * nptl/Makefile (routines): Add libc_pthread_init, + libc_multiple_threads, register-atfork and unregister-atfork. + (libpthread-routines): Add pthread_mutex_cond_lock and pt-fork here. + (gen-as-const-headers): Add lowlevelcond.sym, lowlevelrwlock.sym, + lowlevelbarrier.sym, unwindbuf.sym, lowlevelrobustlock.sym, + pthread-pi-defines.sym, structsem.sym. + * sysdeps/unix/sysv/linux/Makefile [$(subdir) = posix] + (CFLAGS-fork.c, CFLAGS-getpid.o, CFLAGS-getpid.os): New variables. + [$(subdir) = nptl] (tests): Add tst-setgetname. + * nptl/sysdeps/unix/sysv/linux/Makefile: File removed. + * sysdeps/unix/sysv/linux/sigaction.c: Just include + directly here, instead of WRAPPER_INCLUDE. + [!LIBC_SIGACTION]: Remove aliases. + * sysdeps/unix/sysv/linux/aarch64/sigaction.c: Likewise. + * sysdeps/unix/sysv/linux/arm/sigaction.c: Likewise. + * sysdeps/unix/sysv/linux/i386/sigaction.c: Likewise. + * sysdeps/unix/sysv/linux/ia64/sigaction.c: Likewise. + * sysdeps/unix/sysv/linux/mips/sigaction.c: Likewise. + * sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c: Likewise. + * sysdeps/unix/sysv/linux/x86_64/sigaction.c: Likewise. + * nptl/Versions (libc: GLIBC_2.3.2): Add __register_atfork. + (libc: GLIBC_PRIVATE): Add __libc_pthread_init, + __libc_current_sigrtmin_private, __libc_current_sigrtmax_private, + __libc_allocate_rtsig_private. + * nptl/sysdeps/unix/sysv/linux/Versions: File removed. + * sysdeps/unix/sysv/linux/sigtimedwait.c: Include . + * sysdeps/unix/sysv/linux/sigwait.c: Likewise. + * sysdeps/unix/sysv/linux/sigwaitinfo.c: Likewise. + * sysdeps/unix/sysv/linux/sleep.c: Likewise. + * nptl/sysdeps/unix/sysv/linux/sigwait.c: File removed. + * nptl/sysdeps/unix/sysv/linux/sigtimedwait.c: File removed. + * nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c: File removed. + * nptl/sysdeps/unix/sysv/linux/sleep.c: File removed. + * nptl/sysdeps/unix/sysv/linux/createthread.c: File removed. + * sysdeps/unix/sysv/linux/ia64/fork.S: File removed. + * nptl/sysdeps/unix/sysv/linux/internaltypes.h: Moved ... + * nptl/internaltypes.h: ... here. + * nptl/sysdeps/unix/sysv/linux/jmp-unwind.c: Moved ... + * sysdeps/nptl/jmp-unwind.c: ... here. + * nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c: Moved ... + * nptl/libc-lowlevellock.c: ... here. + * nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c: Moved ... + * nptl/libc_multiple_threads.c: ... here. + * nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c: Moved ... + * nptl/libc_pthread_init.c: ... here. + * nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym: Moved ... + * nptl/lowlevelbarrier.sym: ... here. + * nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym: Moved ... + * nptl/lowlevelcond.sym: ... here. + * nptl/sysdeps/unix/sysv/linux/lowlevellock.c: Moved ... + * nptl/lowlevellock.c: ... here. + * nptl/lowlevellock.h: Moved ... + * sysdeps/nptl/lowlevellock.h: ... here. + * nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c: Moved ... + * nptl/lowlevelrobustlock.c: ... here. + * nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym: Moved ... + * nptl/lowlevelrobustlock.sym: ... here. + * nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym: Moved ... + * nptl/lowlevelrwlock.sym: ... here. + * nptl/sysdeps/unix/sysv/linux/pt-fork.c: Moved ... + * nptl/pt-fork.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym: Moved ... + * nptl/pthread-pi-defines.sym: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c: Moved ... + * nptl/pthread_attr_getaffinity.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c: Moved ... + * nptl/pthread_attr_setaffinity.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c: Moved ... + * nptl/pthread_mutex_cond_lock.c: ... here. + * sysdeps/unix/sysv/linux/s390/pthread_mutex_cond_lock.c: + Update #include. + * sysdeps/unix/sysv/linux/x86/pthread_mutex_cond_lock.c: Likewise. + * nptl/sysdeps/unix/sysv/linux/pthread_once.c: Moved ... + * nptl/pthread_once.c: ... here, replacing old file. + * nptl/sysdeps/unix/sysv/linux/pthread_yield.c: Moved ... + * nptl/pthread_yield.c: ... here. + * nptl/sysdeps/unix/sysv/linux/register-atfork.c: Moved ... + * nptl/register-atfork.c: ... here. + * nptl/sysdeps/unix/sysv/linux/sem_post.c: Moved ... + * nptl/sem_post.c: ... here. + * sysdeps/unix/sysv/linux/alpha/sem_post.c: Update #include. + * nptl/sysdeps/unix/sysv/linux/sem_timedwait.c: Moved ... + * nptl/sem_timedwait.c: ... here. + * nptl/sysdeps/unix/sysv/linux/sem_trywait.c: Moved ... + * nptl/sem_trywait.c: ... here. + * sysdeps/sparc/sparc32/sparcv9/sem_trywait.c: Update #include. + * nptl/sysdeps/unix/sysv/linux/sem_wait.c: Moved ... + * nptl/sem_wait.c: ... here. + * nptl/sysdeps/unix/sysv/linux/structsem.sym: Moved ... + * nptl/structsem.sym: ... here. + * nptl/sysdeps/unix/sysv/linux/mq_notify.c: Moved ... + * sysdeps/unix/sysv/linux/mq_notify.c: ... here, replacing old file. + * nptl/sysdeps/unix/sysv/linux/unregister-atfork.c: Moved ... + * nptl/unregister-atfork.c: ... here. + * nptl/sysdeps/unix/sysv/linux/unwindbuf.sym: Moved ... + * nptl/unwindbuf.sym: ... here. + * nptl/sysdeps/unix/sysv/linux/fork.c: Moved ... + * sysdeps/nptl/fork.c: ... here. + * nptl/sysdeps/unix/sysv/linux/fork.h: Moved ... + * sysdeps/nptl/fork.h: ... here. + * sysdeps/unix/sysv/linux/syscalls.list: Remove fork. + * nptl/sysdeps/unix/sysv/linux/aio_misc.h: Moved ... + * sysdeps/unix/sysv/linux/aio_misc.h: ... here. + * nptl/sysdeps/unix/sysv/linux/allocrtsig.c: Moved ... + * sysdeps/unix/sysv/linux/allocrtsig.c: ... here. + * nptl/sysdeps/unix/sysv/linux/getpid.c: Moved ... + * sysdeps/unix/sysv/linux/getpid.c: ... here. + * nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h: Moved ... + * sysdeps/unix/sysv/linux/kernel-posix-timers.h: ... here. + * nptl/sysdeps/unix/sysv/linux/pt-raise.c: Moved ... + * sysdeps/unix/sysv/linux/pt-raise.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c: Moved ... + * sysdeps/unix/sysv/linux/pthread_getaffinity.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: Moved ... + * sysdeps/unix/sysv/linux/pthread_getcpuclockid.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_getname.c: Moved ... + * sysdeps/unix/sysv/linux/pthread_getname.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_kill.c: Moved ... + * sysdeps/unix/sysv/linux/pthread_kill.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c: Moved ... + * sysdeps/unix/sysv/linux/pthread_setaffinity.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_setname.c: Moved ... + * sysdeps/unix/sysv/linux/pthread_setname.c: ... here. + * nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c: Moved ... + * sysdeps/unix/sysv/linux/pthread_sigqueue.c: ... here. + * nptl/sysdeps/unix/sysv/linux/raise.c: Moved ... + * sysdeps/unix/sysv/linux/raise.c: ... here. + * nptl/sysdeps/unix/sysv/linux/timer_create.c: Moved ... + * sysdeps/unix/sysv/linux/timer_create.c: ... here. + * nptl/sysdeps/unix/sysv/linux/timer_delete.c: Moved ... + * sysdeps/unix/sysv/linux/timer_delete.c: ... here. + * nptl/sysdeps/unix/sysv/linux/timer_getoverr.c: Moved ... + * sysdeps/unix/sysv/linux/timer_getoverr.c: ... here. + * nptl/sysdeps/unix/sysv/linux/timer_gettime.c: Moved ... + * sysdeps/unix/sysv/linux/timer_gettime.c: ... here. + * nptl/sysdeps/unix/sysv/linux/timer_routines.c: Moved ... + * sysdeps/unix/sysv/linux/timer_routines.c: ... here. + * nptl/sysdeps/unix/sysv/linux/timer_settime.c: Moved ... + * sysdeps/unix/sysv/linux/timer_settime.c: ... here. + * nptl/sysdeps/unix/sysv/linux/tst-setgetname.c: Moved ... + * sysdeps/unix/sysv/linux/tst-setgetname.c: ... here. + * sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Update #include. + 2014-07-04 Siddhesh Poyarekar * sysdeps/generic/memcopy.h: Add comment for diff --git a/nptl/Makefile b/nptl/Makefile index cd3be126d6..67f7d5bfa9 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -29,7 +29,8 @@ extra-libs-others := $(extra-libs) install-lib-ldscripts := libpthread.so routines = alloca_cutoff forward libc-lowlevellock libc-cancellation \ - libc-cleanup + libc-cleanup libc_pthread_init libc_multiple_threads \ + register-atfork unregister-atfork shared-only-routines = forward libpthread-routines = nptl-init vars events version \ @@ -54,6 +55,7 @@ libpthread-routines = nptl-init vars events version \ pthread_mutex_init pthread_mutex_destroy \ pthread_mutex_lock pthread_mutex_trylock \ pthread_mutex_timedlock pthread_mutex_unlock \ + pthread_mutex_cond_lock \ pthread_mutexattr_init pthread_mutexattr_destroy \ pthread_mutexattr_getpshared \ pthread_mutexattr_setpshared \ @@ -103,7 +105,7 @@ libpthread-routines = nptl-init vars events version \ pt-longjmp pt-cleanup\ cancellation \ lowlevellock lowlevelrobustlock \ - pt-vfork \ + pt-fork pt-vfork \ 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-llseek \ @@ -277,7 +279,12 @@ test-srcs = tst-oddstacklimit # Files which must not be linked with libpthread. tests-nolibpthread = tst-unload -gen-as-const-headers = pthread-errnos.sym +gen-as-const-headers = pthread-errnos.sym \ + lowlevelcond.sym lowlevelrwlock.sym \ + lowlevelbarrier.sym unwindbuf.sym \ + lowlevelrobustlock.sym pthread-pi-defines.sym \ + structsem.sym + LDFLAGS-pthread.so = -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst diff --git a/nptl/Versions b/nptl/Versions index 17a68ed5ee..b7d4a9b9d3 100644 --- a/nptl/Versions +++ b/nptl/Versions @@ -21,6 +21,8 @@ libc { pthread_attr_init; } GLIBC_2.3.2 { + __register_atfork; + # Changed pthread_cond_t. pthread_cond_init; pthread_cond_destroy; pthread_cond_wait; pthread_cond_signal; @@ -31,6 +33,9 @@ libc { # Internal libc interface to libpthread __libc_dl_error_tsd; __libc_vfork; + __libc_pthread_init; + __libc_current_sigrtmin_private; __libc_current_sigrtmax_private; + __libc_allocate_rtsig_private; } } diff --git a/nptl/internaltypes.h b/nptl/internaltypes.h new file mode 100644 index 0000000000..d127f688cf --- /dev/null +++ b/nptl/internaltypes.h @@ -0,0 +1,161 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#ifndef _INTERNALTYPES_H +#define _INTERNALTYPES_H 1 + +#include + + +struct pthread_attr +{ + /* Scheduler parameters and priority. */ + struct sched_param schedparam; + int schedpolicy; + /* Various flags like detachstate, scope, etc. */ + int flags; + /* Size of guard area. */ + size_t guardsize; + /* Stack handling. */ + void *stackaddr; + size_t stacksize; + /* Affinity map. */ + cpu_set_t *cpuset; + size_t cpusetsize; +}; + +#define ATTR_FLAG_DETACHSTATE 0x0001 +#define ATTR_FLAG_NOTINHERITSCHED 0x0002 +#define ATTR_FLAG_SCOPEPROCESS 0x0004 +#define ATTR_FLAG_STACKADDR 0x0008 +#define ATTR_FLAG_OLDATTR 0x0010 +#define ATTR_FLAG_SCHED_SET 0x0020 +#define ATTR_FLAG_POLICY_SET 0x0040 + + +/* Mutex attribute data structure. */ +struct pthread_mutexattr +{ + /* Identifier for the kind of mutex. + + Bit 31 is set if the mutex is to be shared between processes. + + Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify + the type of the mutex. */ + int mutexkind; +}; + + +/* Conditional variable attribute data structure. */ +struct pthread_condattr +{ + /* Combination of values: + + Bit 0 : flag whether conditional variable will be sharable between + processes. + + Bit 1-7: clock ID. */ + int value; +}; + + +/* The __NWAITERS field is used as a counter and to house the number + of bits for other purposes. COND_CLOCK_BITS is the number + of bits needed to represent the ID of the clock. COND_NWAITERS_SHIFT + is the number of bits reserved for other purposes like the clock. */ +#define COND_CLOCK_BITS 1 +#define COND_NWAITERS_SHIFT 1 + + +/* Read-write lock variable attribute data structure. */ +struct pthread_rwlockattr +{ + int lockkind; + int pshared; +}; + + +/* Barrier data structure. */ +struct pthread_barrier +{ + unsigned int curr_event; + int lock; + unsigned int left; + unsigned int init_count; + int private; +}; + + +/* Barrier variable attribute data structure. */ +struct pthread_barrierattr +{ + int pshared; +}; + + +/* Thread-local data handling. */ +struct pthread_key_struct +{ + /* Sequence numbers. Even numbers indicated vacant entries. Note + that zero is even. We use uintptr_t to not require padding on + 32- and 64-bit machines. On 64-bit machines it helps to avoid + wrapping, too. */ + uintptr_t seq; + + /* Destructor for the data. */ + void (*destr) (void *); +}; + +/* Check whether an entry is unused. */ +#define KEY_UNUSED(p) (((p) & 1) == 0) +/* Check whether a key is usable. We cannot reuse an allocated key if + the sequence counter would overflow after the next destroy call. + This would mean that we potentially free memory for a key with the + same sequence. This is *very* unlikely to happen, A program would + have to create and destroy a key 2^31 times (on 32-bit platforms, + on 64-bit platforms that would be 2^63). If it should happen we + simply don't use this specific key anymore. */ +#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2))) + + +/* Handling of read-write lock data. */ +// XXX For now there is only one flag. Maybe more in future. +#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0) + + +/* Semaphore variable structure. */ +struct new_sem +{ + unsigned int value; + int private; + unsigned long int nwaiters; +}; + +struct old_sem +{ + unsigned int value; +}; + + +/* Compatibility type for old conditional variable interfaces. */ +typedef struct +{ + pthread_cond_t *cond; +} pthread_cond_2_0_t; + +#endif /* internaltypes.h */ diff --git a/nptl/libc-lowlevellock.c b/nptl/libc-lowlevellock.c new file mode 100644 index 0000000000..080d4bdafb --- /dev/null +++ b/nptl/libc-lowlevellock.c @@ -0,0 +1,20 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + 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, see + . */ + +/* No difference to lowlevellock.c, except we lose a couple of functions. */ +#include diff --git a/nptl/libc_multiple_threads.c b/nptl/libc_multiple_threads.c new file mode 100644 index 0000000000..acf3594d71 --- /dev/null +++ b/nptl/libc_multiple_threads.c @@ -0,0 +1,28 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include + +#ifndef NOT_IN_libc +# ifndef TLS_MULTIPLE_THREADS_IN_TCB +/* Variable set to a nonzero value either if more than one thread runs or ran, + or if a single-threaded process is trying to cancel itself. See + nptl/descr.h for more context on the single-threaded process case. */ +int __libc_multiple_threads attribute_hidden; +# endif +#endif diff --git a/nptl/libc_pthread_init.c b/nptl/libc_pthread_init.c new file mode 100644 index 0000000000..4d8d710cca --- /dev/null +++ b/nptl/libc_pthread_init.c @@ -0,0 +1,86 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#ifdef TLS_MULTIPLE_THREADS_IN_TCB +void +#else +extern int __libc_multiple_threads attribute_hidden; + +int * +#endif +__libc_pthread_init (ptr, reclaim, functions) + unsigned long int *ptr; + void (*reclaim) (void); + const struct pthread_functions *functions; +{ + /* Remember the pointer to the generation counter in libpthread. */ + __fork_generation_pointer = ptr; + + /* Called by a child after fork. */ + __register_atfork (NULL, NULL, reclaim, NULL); + +#ifdef SHARED + /* Copy the function pointers into an array in libc. This enables + access with just one memory reference but moreso, it prevents + hijacking the function pointers with just one pointer change. We + "encrypt" the function pointers since we cannot write-protect the + array easily enough. */ + union ptrhack + { + struct pthread_functions pf; +# define NPTRS (sizeof (struct pthread_functions) / sizeof (void *)) + void *parr[NPTRS]; + } __attribute__ ((may_alias)) const *src; + union ptrhack *dest; + + src = (const void *) functions; + dest = (void *) &__libc_pthread_functions; + + for (size_t cnt = 0; cnt < NPTRS; ++cnt) + { + void *p = src->parr[cnt]; + PTR_MANGLE (p); + dest->parr[cnt] = p; + } + __libc_pthread_functions_init = 1; +#endif + +#ifndef TLS_MULTIPLE_THREADS_IN_TCB + return &__libc_multiple_threads; +#endif +} + +#ifdef SHARED +libc_freeres_fn (freeres_libptread) +{ + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr_freeres, ()); +} +#endif diff --git a/nptl/lowlevelbarrier.sym b/nptl/lowlevelbarrier.sym new file mode 100644 index 0000000000..cfe22b0892 --- /dev/null +++ b/nptl/lowlevelbarrier.sym @@ -0,0 +1,12 @@ +#include +#include +#include +#include "internaltypes.h" + +-- + +CURR_EVENT offsetof (struct pthread_barrier, curr_event) +MUTEX offsetof (struct pthread_barrier, lock) +LEFT offsetof (struct pthread_barrier, left) +INIT_COUNT offsetof (struct pthread_barrier, init_count) +PRIVATE offsetof (struct pthread_barrier, private) diff --git a/nptl/lowlevelcond.sym b/nptl/lowlevelcond.sym new file mode 100644 index 0000000000..18e1adad43 --- /dev/null +++ b/nptl/lowlevelcond.sym @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +-- + +cond_lock offsetof (pthread_cond_t, __data.__lock) +cond_futex offsetof (pthread_cond_t, __data.__futex) +cond_nwaiters offsetof (pthread_cond_t, __data.__nwaiters) +total_seq offsetof (pthread_cond_t, __data.__total_seq) +wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) +woken_seq offsetof (pthread_cond_t, __data.__woken_seq) +dep_mutex offsetof (pthread_cond_t, __data.__mutex) +broadcast_seq offsetof (pthread_cond_t, __data.__broadcast_seq) +nwaiters_shift COND_NWAITERS_SHIFT diff --git a/nptl/lowlevellock.c b/nptl/lowlevellock.c new file mode 100644 index 0000000000..e198af7e8d --- /dev/null +++ b/nptl/lowlevellock.c @@ -0,0 +1,124 @@ +/* low level locking for pthread library. Generic futex-using version. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include + +void +__lll_lock_wait_private (int *futex) +{ + if (*futex == 2) + lll_futex_wait (futex, 2, LLL_PRIVATE); + + while (atomic_exchange_acq (futex, 2) != 0) + lll_futex_wait (futex, 2, LLL_PRIVATE); +} + + +/* These functions don't get included in libc.so */ +#ifdef IS_IN_libpthread +void +__lll_lock_wait (int *futex, int private) +{ + if (*futex == 2) + lll_futex_wait (futex, 2, private); + + while (atomic_exchange_acq (futex, 2) != 0) + lll_futex_wait (futex, 2, private); +} + + +int +__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Try locking. */ + while (atomic_exchange_acq (futex, 2) != 0) + { + struct timeval tv; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + struct timespec rt; + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait. */ + lll_futex_timed_wait (futex, 2, &rt, private); + } + + return 0; +} + + +int +__lll_timedwait_tid (int *tidp, const struct timespec *abstime) +{ + int tid; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Repeat until thread terminated. */ + while ((tid = *tidp) != 0) + { + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; + + /* Wait until thread terminates. The kernel so far does not use + the private futex operations for this. */ + if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) + return ETIMEDOUT; + } + + return 0; +} +#endif diff --git a/nptl/lowlevellock.h b/nptl/lowlevellock.h deleted file mode 100644 index 7d1913a58d..0000000000 --- a/nptl/lowlevellock.h +++ /dev/null @@ -1,83 +0,0 @@ -/* Low level locking macros used in NPTL implementation. Stub version. - Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include - - -/* Mutex lock counter: - bit 31 clear means unlocked; - bit 31 set means locked. - - All code that looks at bit 31 first increases the 'number of - interested threads' usage counter, which is in bits 0-30. - - All negative mutex values indicate that the mutex is still locked. */ - - -static inline void -__generic_mutex_lock (int *mutex) -{ - unsigned int v; - - /* Bit 31 was clear, we got the mutex. (this is the fastpath). */ - if (atomic_bit_test_set (mutex, 31) == 0) - return; - - atomic_increment (mutex); - - while (1) - { - if (atomic_bit_test_set (mutex, 31) == 0) - { - atomic_decrement (mutex); - return; - } - - /* We have to wait now. First make sure the futex value we are - monitoring is truly negative (i.e. locked). */ - v = *mutex; - if (v >= 0) - continue; - - lll_futex_wait (mutex, v, - // XYZ check mutex flag - LLL_SHARED); - } -} - - -static inline void -__generic_mutex_unlock (int *mutex) -{ - /* Adding 0x80000000 to the counter results in 0 if and only if - there are not other interested threads - we can return (this is - the fastpath). */ - if (atomic_add_zero (mutex, 0x80000000)) - return; - - /* There are other threads waiting for this mutex, wake one of them - up. */ - lll_futex_wake (mutex, 1, - // XYZ check mutex flag - LLL_SHARED); -} - - -#define lll_mutex_lock(futex) __generic_mutex_lock (&(futex)) -#define lll_mutex_unlock(futex) __generic_mutex_unlock (&(futex)) diff --git a/nptl/lowlevelrobustlock.c b/nptl/lowlevelrobustlock.c new file mode 100644 index 0000000000..35258071cf --- /dev/null +++ b/nptl/lowlevelrobustlock.c @@ -0,0 +1,128 @@ +/* Copyright (C) 2006-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2006. + + 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, see + . */ + +#include +#include +#include +#include +#include +#include + + +int +__lll_robust_lock_wait (int *futex, int private) +{ + int oldval = *futex; + int tid = THREAD_GETMEM (THREAD_SELF, tid); + + /* If the futex changed meanwhile try locking again. */ + if (oldval == 0) + goto try; + + do + { + if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED)) + return oldval; + + int newval = oldval | FUTEX_WAITERS; + if (oldval != newval + && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) + continue; + + lll_futex_wait (futex, newval, private); + + try: + ; + } + while ((oldval = atomic_compare_and_exchange_val_acq (futex, + tid | FUTEX_WAITERS, + 0)) != 0); + return 0; +} + + +int +__lll_robust_timedlock_wait (int *futex, const struct timespec *abstime, + int private) +{ + /* Reject invalid timeouts. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + int tid = THREAD_GETMEM (THREAD_SELF, tid); + int oldval = *futex; + + /* If the futex changed meanwhile try locking again. */ + if (oldval == 0) + goto try; + + /* Work around the fact that the kernel rejects negative timeout values + despite them being valid. */ + if (__glibc_unlikely (abstime->tv_sec < 0)) + return ETIMEDOUT; + + do + { +#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ + || !defined lll_futex_timed_wait_bitset) + struct timeval tv; + struct timespec rt; + + /* Get the current time. */ + (void) __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + + /* Already timed out? */ + if (rt.tv_sec < 0) + return ETIMEDOUT; +#endif + + /* Wait. */ + if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED)) + return oldval; + + int newval = oldval | FUTEX_WAITERS; + if (oldval != newval + && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) + continue; + +#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ + || !defined lll_futex_timed_wait_bitset) + lll_futex_timed_wait (futex, newval, &rt, private); +#else + lll_futex_timed_wait_bitset (futex, newval, abstime, + FUTEX_CLOCK_REALTIME, private); +#endif + + try: + ; + } + while ((oldval = atomic_compare_and_exchange_val_acq (futex, + tid | FUTEX_WAITERS, + 0)) != 0); + + return 0; +} diff --git a/nptl/lowlevelrobustlock.sym b/nptl/lowlevelrobustlock.sym new file mode 100644 index 0000000000..2f1e9da52b --- /dev/null +++ b/nptl/lowlevelrobustlock.sym @@ -0,0 +1,6 @@ +#include +#include + +-- + +TID offsetof (struct pthread, tid) diff --git a/nptl/lowlevelrwlock.sym b/nptl/lowlevelrwlock.sym new file mode 100644 index 0000000000..f50b25bfb8 --- /dev/null +++ b/nptl/lowlevelrwlock.sym @@ -0,0 +1,16 @@ +#include +#include +#include +#include + +-- + +MUTEX offsetof (pthread_rwlock_t, __data.__lock) +NR_READERS offsetof (pthread_rwlock_t, __data.__nr_readers) +READERS_WAKEUP offsetof (pthread_rwlock_t, __data.__readers_wakeup) +WRITERS_WAKEUP offsetof (pthread_rwlock_t, __data.__writer_wakeup) +READERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_readers_queued) +WRITERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_writers_queued) +FLAGS offsetof (pthread_rwlock_t, __data.__flags) +WRITER offsetof (pthread_rwlock_t, __data.__writer) +PSHARED offsetof (pthread_rwlock_t, __data.__shared) diff --git a/nptl/pt-fork.c b/nptl/pt-fork.c new file mode 100644 index 0000000000..582409486e --- /dev/null +++ b/nptl/pt-fork.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include + + +pid_t +__fork (void) +{ + return __libc_fork (); +} +strong_alias (__fork, fork) diff --git a/nptl/pthread-pi-defines.sym b/nptl/pthread-pi-defines.sym new file mode 100644 index 0000000000..0ac51dba98 --- /dev/null +++ b/nptl/pthread-pi-defines.sym @@ -0,0 +1,9 @@ +#include + +-- These PI macros are used by assembly code. + +MUTEX_KIND offsetof (pthread_mutex_t, __data.__kind) +ROBUST_BIT PTHREAD_MUTEX_ROBUST_NORMAL_NP +PI_BIT PTHREAD_MUTEX_PRIO_INHERIT_NP +PS_BIT PTHREAD_MUTEX_PSHARED_BIT +TID_MASK FUTEX_TID_MASK diff --git a/nptl/pthread_attr_getaffinity.c b/nptl/pthread_attr_getaffinity.c new file mode 100644 index 0000000000..c80fef47c4 --- /dev/null +++ b/nptl/pthread_attr_getaffinity.c @@ -0,0 +1,74 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +int +__pthread_attr_getaffinity_new (const pthread_attr_t *attr, size_t cpusetsize, + cpu_set_t *cpuset) +{ + const struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (const struct pthread_attr *) attr; + + if (iattr->cpuset != NULL) + { + /* Check whether there are any bits set beyond the limits + the user requested. */ + for (size_t cnt = cpusetsize; cnt < iattr->cpusetsize; ++cnt) + if (((char *) iattr->cpuset)[cnt] != 0) + return EINVAL; + + /* Copy over the cpuset from the thread attribute object. Limit the copy + to the minimum of the source and destination sizes to prevent a buffer + overrun. If the destination is larger, fill the remaining space with + zeroes. */ + void *p = mempcpy (cpuset, iattr->cpuset, + MIN (iattr->cpusetsize, cpusetsize)); + if (cpusetsize > iattr->cpusetsize) + memset (p, '\0', cpusetsize - iattr->cpusetsize); + } + else + /* We have no information. */ + memset (cpuset, -1, cpusetsize); + + return 0; +} +versioned_symbol (libpthread, __pthread_attr_getaffinity_new, + pthread_attr_getaffinity_np, GLIBC_2_3_4); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) +int +__pthread_attr_getaffinity_old (const pthread_attr_t *attr, cpu_set_t *cpuset) +{ + /* The old interface by default assumed a 1024 processor bitmap. */ + return __pthread_attr_getaffinity_new (attr, 128, cpuset); +} +compat_symbol (libpthread, __pthread_attr_getaffinity_old, + pthread_attr_getaffinity_np, GLIBC_2_3_3); +#endif diff --git a/nptl/pthread_attr_setaffinity.c b/nptl/pthread_attr_setaffinity.c new file mode 100644 index 0000000000..96c52ea531 --- /dev/null +++ b/nptl/pthread_attr_setaffinity.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include +#include +#include + + + + +int +__pthread_attr_setaffinity_new (pthread_attr_t *attr, size_t cpusetsize, + const cpu_set_t *cpuset) +{ + struct pthread_attr *iattr; + + assert (sizeof (*attr) >= sizeof (struct pthread_attr)); + iattr = (struct pthread_attr *) attr; + + if (cpuset == NULL || cpusetsize == 0) + { + free (iattr->cpuset); + iattr->cpuset = NULL; + iattr->cpusetsize = 0; + } + else + { + int ret = check_cpuset_attr (cpuset, cpusetsize); + + if (ret) + return ret; + + if (iattr->cpusetsize != cpusetsize) + { + void *newp = (cpu_set_t *) realloc (iattr->cpuset, cpusetsize); + if (newp == NULL) + return ENOMEM; + + iattr->cpuset = newp; + iattr->cpusetsize = cpusetsize; + } + + memcpy (iattr->cpuset, cpuset, cpusetsize); + } + + return 0; +} +versioned_symbol (libpthread, __pthread_attr_setaffinity_new, + pthread_attr_setaffinity_np, GLIBC_2_3_4); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) +int +__pthread_attr_setaffinity_old (pthread_attr_t *attr, cpu_set_t *cpuset) +{ + /* The old interface by default assumed a 1024 processor bitmap. */ + return __pthread_attr_setaffinity_new (attr, 128, cpuset); +} +compat_symbol (libpthread, __pthread_attr_setaffinity_old, + pthread_attr_setaffinity_np, GLIBC_2_3_3); +#endif diff --git a/nptl/pthread_mutex_cond_lock.c b/nptl/pthread_mutex_cond_lock.c new file mode 100644 index 0000000000..7b6fbc18aa --- /dev/null +++ b/nptl/pthread_mutex_cond_lock.c @@ -0,0 +1,21 @@ +#include + +#define LLL_MUTEX_LOCK(mutex) \ + lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)) + +/* Not actually elided so far. Needed? */ +#define LLL_MUTEX_LOCK_ELISION(mutex) \ + ({ lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)); 0; }) + +#define LLL_MUTEX_TRYLOCK(mutex) \ + lll_cond_trylock ((mutex)->__data.__lock) +#define LLL_MUTEX_TRYLOCK_ELISION(mutex) LLL_MUTEX_TRYLOCK(mutex) + +#define LLL_ROBUST_MUTEX_LOCK(mutex, id) \ + lll_robust_cond_lock ((mutex)->__data.__lock, id, \ + PTHREAD_ROBUST_MUTEX_PSHARED (mutex)) +#define __pthread_mutex_lock __pthread_mutex_cond_lock +#define __pthread_mutex_lock_full __pthread_mutex_cond_lock_full +#define NO_INCR + +#include diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c index 664b048acb..10c01d6023 100644 --- a/nptl/pthread_once.c +++ b/nptl/pthread_once.c @@ -1,6 +1,6 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2002. + Contributed by Jakub Jelinek , 2003. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -9,7 +9,7 @@ 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 + 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 @@ -18,37 +18,114 @@ #include "pthreadP.h" #include +#include +unsigned long int __fork_generation attribute_hidden; -static int once_lock = LLL_LOCK_INITIALIZER; +static void +clear_once_control (void *arg) +{ + pthread_once_t *once_control = (pthread_once_t *) arg; + + /* Reset to the uninitialized state here. We don't need a stronger memory + order because we do not need to make any other of our writes visible to + other threads that see this value: This function will be called if we + get interrupted (see __pthread_once), so all we need to relay to other + threads is the state being reset again. */ + *once_control = 0; + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); +} + +/* This is similar to a lock implementation, but we distinguish between three + states: not yet initialized (0), initialization finished (2), and + initialization in progress (__fork_generation | 1). If in the first state, + threads will try to run the initialization by moving to the second state; + the first thread to do so via a CAS on once_control runs init_routine, + other threads block. + When forking the process, some threads can be interrupted during the second + state; they won't be present in the forked child, so we need to restart + initialization in the child. To distinguish an in-progress initialization + from an interrupted initialization (in which case we need to reclaim the + lock), we look at the fork generation that's part of the second state: We + can reclaim iff it differs from the current fork generation. + XXX: This algorithm has an ABA issue on the fork generation: If an + initialization is interrupted, we then fork 2^30 times (30 bits of + once_control are used for the fork generation), and try to initialize + again, we can deadlock because we can't distinguish the in-progress and + interrupted cases anymore. */ int __pthread_once (once_control, init_routine) pthread_once_t *once_control; void (*init_routine) (void); { - /* XXX Depending on whether the LOCK_IN_ONCE_T is defined use a - global lock variable or one which is part of the pthread_once_t - object. */ - if (*once_control == PTHREAD_ONCE_INIT) + while (1) { - lll_lock (once_lock, LLL_PRIVATE); + int oldval, val, newval; - /* XXX This implementation is not complete. It doesn't take - cancelation and fork into account. */ - if (*once_control == PTHREAD_ONCE_INIT) + /* We need acquire memory order for this load because if the value + signals that initialization has finished, we need to be see any + data modifications done during initialization. */ + val = *once_control; + atomic_read_barrier(); + do { - init_routine (); + /* Check if the initialization has already been done. */ + if (__glibc_likely ((val & 2) != 0)) + return 0; + + oldval = val; + /* We try to set the state to in-progress and having the current + fork generation. We don't need atomic accesses for the fork + generation because it's immutable in a particular process, and + forked child processes start with a single thread that modified + the generation. */ + newval = __fork_generation | 1; + /* We need acquire memory order here for the same reason as for the + load from once_control above. */ + val = atomic_compare_and_exchange_val_acq (once_control, newval, + oldval); + } + while (__glibc_unlikely (val != oldval)); - *once_control = !PTHREAD_ONCE_INIT; + /* Check if another thread already runs the initializer. */ + if ((oldval & 1) != 0) + { + /* Check whether the initializer execution was interrupted by a + fork. We know that for both values, bit 0 is set and bit 1 is + not. */ + if (oldval == newval) + { + /* Same generation, some other thread was faster. Wait. */ + lll_futex_wait (once_control, newval, LLL_PRIVATE); + continue; + } } - lll_unlock (once_lock, LLL_PRIVATE); + /* This thread is the first here. Do the initialization. + Register a cleanup handler so that in case the thread gets + interrupted the initialization can be restarted. */ + pthread_cleanup_push (clear_once_control, once_control); + + init_routine (); + + pthread_cleanup_pop (0); + + + /* Mark *once_control as having finished the initialization. We need + release memory order here because we need to synchronize with other + threads that want to use the initialized data. */ + atomic_write_barrier(); + *once_control = 2; + + /* Wake up all other threads. */ + lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); + break; } return 0; } -strong_alias (__pthread_once, pthread_once) +weak_alias (__pthread_once, pthread_once) hidden_def (__pthread_once) diff --git a/nptl/pthread_yield.c b/nptl/pthread_yield.c new file mode 100644 index 0000000000..7f5f2065d3 --- /dev/null +++ b/nptl/pthread_yield.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include +#include + + +/* With the 1-on-1 model we implement this function is equivalent to + the 'sched_yield' function. */ +int +pthread_yield (void) +{ + return sched_yield (); +} diff --git a/nptl/register-atfork.c b/nptl/register-atfork.c new file mode 100644 index 0000000000..2cc49540b9 --- /dev/null +++ b/nptl/register-atfork.c @@ -0,0 +1,145 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include +#include +#include +#include +#include + + +/* Lock to protect allocation and deallocation of fork handlers. */ +int __fork_lock = LLL_LOCK_INITIALIZER; + + +/* Number of pre-allocated handler entries. */ +#define NHANDLER 48 + +/* Memory pool for fork handler structures. */ +static struct fork_handler_pool +{ + struct fork_handler_pool *next; + struct fork_handler mem[NHANDLER]; +} fork_handler_pool; + + +static struct fork_handler * +fork_handler_alloc (void) +{ + struct fork_handler_pool *runp = &fork_handler_pool; + struct fork_handler *result = NULL; + unsigned int i; + + do + { + /* Search for an empty entry. */ + for (i = 0; i < NHANDLER; ++i) + if (runp->mem[i].refcntr == 0) + goto found; + } + while ((runp = runp->next) != NULL); + + /* We have to allocate a new entry. */ + runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp)); + if (runp != NULL) + { + /* Enqueue the new memory pool into the list. */ + runp->next = fork_handler_pool.next; + fork_handler_pool.next = runp; + + /* We use the last entry on the page. This means when we start + searching from the front the next time we will find the first + entry unused. */ + i = NHANDLER - 1; + + found: + result = &runp->mem[i]; + result->refcntr = 1; + result->need_signal = 0; + } + + return result; +} + + +int +__register_atfork (prepare, parent, child, dso_handle) + void (*prepare) (void); + void (*parent) (void); + void (*child) (void); + void *dso_handle; +{ + /* Get the lock to not conflict with other allocations. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + struct fork_handler *newp = fork_handler_alloc (); + + if (newp != NULL) + { + /* Initialize the new record. */ + newp->prepare_handler = prepare; + newp->parent_handler = parent; + newp->child_handler = child; + newp->dso_handle = dso_handle; + + __linkin_atfork (newp); + } + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + return newp == NULL ? ENOMEM : 0; +} +libc_hidden_def (__register_atfork) + + +void +attribute_hidden +__linkin_atfork (struct fork_handler *newp) +{ + do + newp->next = __fork_handlers; + while (catomic_compare_and_exchange_bool_acq (&__fork_handlers, + newp, newp->next) != 0); +} + + +libc_freeres_fn (free_mem) +{ + /* Get the lock to not conflict with running forks. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + /* No more fork handlers. */ + __fork_handlers = NULL; + + /* Free eventually allocated memory blocks for the object pool. */ + struct fork_handler_pool *runp = fork_handler_pool.next; + + memset (&fork_handler_pool, '\0', sizeof (fork_handler_pool)); + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + /* We can free the memory after releasing the lock. */ + while (runp != NULL) + { + struct fork_handler_pool *oldp = runp; + runp = runp->next; + free (oldp); + } +} diff --git a/nptl/sem_post.c b/nptl/sem_post.c new file mode 100644 index 0000000000..4906adf332 --- /dev/null +++ b/nptl/sem_post.c @@ -0,0 +1,80 @@ +/* sem_post -- post to a POSIX semaphore. Generic futex-using version. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include +#include + +#include + +int +__new_sem_post (sem_t *sem) +{ + struct new_sem *isem = (struct new_sem *) sem; + + __typeof (isem->value) cur; + do + { + cur = isem->value; + if (isem->value == SEM_VALUE_MAX) + { + __set_errno (EOVERFLOW); + return -1; + } + } + while (atomic_compare_and_exchange_bool_rel (&isem->value, cur + 1, cur)); + + atomic_full_barrier (); + if (isem->nwaiters > 0) + { + int err = lll_futex_wake (&isem->value, 1, + isem->private ^ FUTEX_PRIVATE_FLAG); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + } + return 0; +} +versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +int +attribute_compat_text_section +__old_sem_post (sem_t *sem) +{ + int *futex = (int *) sem; + + (void) atomic_increment_val (futex); + /* We always have to assume it is a shared semaphore. */ + int err = lll_futex_wake (futex, 1, LLL_SHARED); + if (__builtin_expect (err, 0) < 0) + { + __set_errno (-err); + return -1; + } + return 0; +} +compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); +#endif diff --git a/nptl/sem_timedwait.c b/nptl/sem_timedwait.c new file mode 100644 index 0000000000..7dfe51dd8b --- /dev/null +++ b/nptl/sem_timedwait.c @@ -0,0 +1,116 @@ +/* sem_timedwait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include + +#include +#include + + +extern void __sem_wait_cleanup (void *arg) attribute_hidden; + +/* This is in a seperate function in order to make sure gcc + puts the call site into an exception region, and thus the + cleanups get properly run. */ +static int +__attribute__ ((noinline)) +do_futex_timed_wait (struct new_sem *isem, struct timespec *rt) +{ + int err, oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_timed_wait (&isem->value, 0, rt, + isem->private ^ FUTEX_PRIVATE_FLAG); + + __pthread_disable_asynccancel (oldtype); + return err; +} + +int +sem_timedwait (sem_t *sem, const struct timespec *abstime) +{ + struct new_sem *isem = (struct new_sem *) sem; + int err; + + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + { + __set_errno (EINVAL); + return -1; + } + + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + struct timeval tv; + struct timespec rt; + int sec, nsec; + + /* Get the current time. */ + __gettimeofday (&tv, NULL); + + /* Compute relative timeout. */ + sec = abstime->tv_sec - tv.tv_sec; + nsec = abstime->tv_nsec - tv.tv_usec * 1000; + if (nsec < 0) + { + nsec += 1000000000; + --sec; + } + + /* Already timed out? */ + if (sec < 0) + { + __set_errno (ETIMEDOUT); + err = -1; + break; + } + + /* Do wait. */ + rt.tv_sec = sec; + rt.tv_nsec = nsec; + err = do_futex_timed_wait(isem, &rt); + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; +} diff --git a/nptl/sem_trywait.c b/nptl/sem_trywait.c new file mode 100644 index 0000000000..94c323c18e --- /dev/null +++ b/nptl/sem_trywait.c @@ -0,0 +1,50 @@ +/* sem_trywait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include +#include + +#include + + +int +__new_sem_trywait (sem_t *sem) +{ + int *futex = (int *) sem; + int val; + + if (*futex > 0) + { + val = atomic_decrement_if_positive (futex); + if (val > 0) + return 0; + } + + __set_errno (EAGAIN); + return -1; +} +versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +strong_alias (__new_sem_trywait, __old_sem_trywait) +compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); +#endif diff --git a/nptl/sem_wait.c b/nptl/sem_wait.c new file mode 100644 index 0000000000..b12babb596 --- /dev/null +++ b/nptl/sem_wait.c @@ -0,0 +1,123 @@ +/* sem_wait -- wait on a semaphore. Generic futex-using version. + Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Paul Mackerras , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include + +#include +#include +#include + + +void +attribute_hidden +__sem_wait_cleanup (void *arg) +{ + struct new_sem *isem = (struct new_sem *) arg; + + atomic_decrement (&isem->nwaiters); +} + +/* This is in a seperate function in order to make sure gcc + puts the call site into an exception region, and thus the + cleanups get properly run. */ +static int +__attribute__ ((noinline)) +do_futex_wait (struct new_sem *isem) +{ + int err, oldtype = __pthread_enable_asynccancel (); + + err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG); + + __pthread_disable_asynccancel (oldtype); + return err; +} + +int +__new_sem_wait (sem_t *sem) +{ + struct new_sem *isem = (struct new_sem *) sem; + int err; + + if (atomic_decrement_if_positive (&isem->value) > 0) + return 0; + + atomic_increment (&isem->nwaiters); + + pthread_cleanup_push (__sem_wait_cleanup, isem); + + while (1) + { + err = do_futex_wait(isem); + if (err != 0 && err != -EWOULDBLOCK) + { + __set_errno (-err); + err = -1; + break; + } + + if (atomic_decrement_if_positive (&isem->value) > 0) + { + err = 0; + break; + } + } + + pthread_cleanup_pop (0); + + atomic_decrement (&isem->nwaiters); + + return err; +} +versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) +int +attribute_compat_text_section +__old_sem_wait (sem_t *sem) +{ + int *futex = (int *) sem; + int err; + + do + { + if (atomic_decrement_if_positive (futex) > 0) + return 0; + + /* Enable asynchronous cancellation. Required by the standard. */ + int oldtype = __pthread_enable_asynccancel (); + + /* Always assume the semaphore is shared. */ + err = lll_futex_wait (futex, 0, LLL_SHARED); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (oldtype); + } + while (err == 0 || err == -EWOULDBLOCK); + + __set_errno (-err); + return -1; +} + +compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); +#endif diff --git a/nptl/structsem.sym b/nptl/structsem.sym new file mode 100644 index 0000000000..0e2a15f2b5 --- /dev/null +++ b/nptl/structsem.sym @@ -0,0 +1,12 @@ +#include +#include +#include +#include +#include "internaltypes.h" + +-- + +VALUE offsetof (struct new_sem, value) +PRIVATE offsetof (struct new_sem, private) +NWAITERS offsetof (struct new_sem, nwaiters) +SEM_VALUE_MAX SEM_VALUE_MAX diff --git a/nptl/sysdeps/unix/sysv/linux/Makefile b/nptl/sysdeps/unix/sysv/linux/Makefile deleted file mode 100644 index 1a5a29df69..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (C) 2002-2014 Free Software Foundation, Inc. -# This file is part of the GNU C Library. -# Contributed by Ulrich Drepper , 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, see -# . - -ifeq ($(subdir),nptl) -sysdep_routines += register-atfork unregister-atfork libc_pthread_init \ - libc_multiple_threads - -libpthread-sysdep_routines += pt-fork pthread_mutex_cond_lock - -gen-as-const-headers += lowlevelcond.sym lowlevelrwlock.sym \ - lowlevelbarrier.sym unwindbuf.sym \ - lowlevelrobustlock.sym pthread-pi-defines.sym \ - structsem.sym -tests += tst-setgetname -endif - -ifeq ($(subdir),posix) -CFLAGS-fork.c = $(libio-mtsafe) -CFLAGS-getpid.o = -fomit-frame-pointer -CFLAGS-getpid.os = -fomit-frame-pointer -endif - -# Needed in both the signal and nptl subdir. -CFLAGS-sigaction.c = -DWRAPPER_INCLUDE='' diff --git a/nptl/sysdeps/unix/sysv/linux/Versions b/nptl/sysdeps/unix/sysv/linux/Versions deleted file mode 100644 index d18255521c..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/Versions +++ /dev/null @@ -1,15 +0,0 @@ -libc { - GLIBC_2.3.2 { - __register_atfork; - } - GLIBC_PRIVATE { - __libc_pthread_init; - __libc_current_sigrtmin_private; __libc_current_sigrtmax_private; - __libc_allocate_rtsig_private; - } -} -libpthread { - GLIBC_2.0 { - fork; __fork; - } -} diff --git a/nptl/sysdeps/unix/sysv/linux/aio_misc.h b/nptl/sysdeps/unix/sysv/linux/aio_misc.h deleted file mode 100644 index 58ac45153f..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/aio_misc.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (C) 2004-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek , 2004. - - 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, see . */ - -#ifndef _AIO_MISC_H -# include_next -# include -# include -# include -# include - -# define aio_start_notify_thread __aio_start_notify_thread -# define aio_create_helper_thread __aio_create_helper_thread - -extern inline void -__aio_start_notify_thread (void) -{ - sigset_t ss; - sigemptyset (&ss); - INTERNAL_SYSCALL_DECL (err); - INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); -} - -extern inline int -__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), - void *arg) -{ - pthread_attr_t attr; - - /* Make sure the thread is created detached. */ - pthread_attr_init (&attr); - pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); - - /* The helper thread needs only very little resources. */ - (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); - - /* Block all signals in the helper thread. To do this thoroughly we - temporarily have to block all signals here. */ - sigset_t ss; - sigset_t oss; - sigfillset (&ss); - INTERNAL_SYSCALL_DECL (err); - INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); - - int ret = pthread_create (threadp, &attr, tf, arg); - - /* Restore the signal mask. */ - INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, - _NSIG / 8); - - (void) pthread_attr_destroy (&attr); - return ret; -} -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/allocrtsig.c b/nptl/sysdeps/unix/sysv/linux/allocrtsig.c deleted file mode 100644 index 0ed7d089c6..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/allocrtsig.c +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include - - -static int current_rtmin = __SIGRTMIN + 2; -static int current_rtmax = __SIGRTMAX; - - -/* We reserve __SIGRTMIN for use as the cancelation signal. This - signal is used internally. */ -int -__libc_current_sigrtmin (void) -{ - return current_rtmin; -} -libc_hidden_def (__libc_current_sigrtmin) -strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private) - - -int -__libc_current_sigrtmax (void) -{ - return current_rtmax; -} -libc_hidden_def (__libc_current_sigrtmax) -strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private) - - -int -__libc_allocate_rtsig (int high) -{ - 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/nptl/sysdeps/unix/sysv/linux/createthread.c b/nptl/sysdeps/unix/sysv/linux/createthread.c deleted file mode 100644 index 9a21f3997a..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/createthread.c +++ /dev/null @@ -1,23 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky . - - 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, see - . */ - -/* Value passed to 'clone' for initialization of the thread register. */ -#define TLS_VALUE pd - -/* Get the real implementation. */ -#include diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c deleted file mode 100644 index 70201a294c..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/fork.c +++ /dev/null @@ -1,238 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -unsigned long int *__fork_generation_pointer; - - - -/* The single linked list of all currently registered fork handlers. */ -struct fork_handler *__fork_handlers; - - -static void -fresetlockfiles (void) -{ - _IO_ITER i; - - for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i)) - _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock)); -} - - -pid_t -__libc_fork (void) -{ - pid_t pid; - struct used_handler - { - struct fork_handler *handler; - struct used_handler *next; - } *allp = NULL; - - /* Run all the registered preparation handlers. In reverse order. - While doing this we build up a list of all the entries. */ - struct fork_handler *runp; - while ((runp = __fork_handlers) != NULL) - { - /* Make sure we read from the current RUNP pointer. */ - atomic_full_barrier (); - - unsigned int oldval = runp->refcntr; - - if (oldval == 0) - /* This means some other thread removed the list just after - the pointer has been loaded. Try again. Either the list - is empty or we can retry it. */ - continue; - - /* Bump the reference counter. */ - if (atomic_compare_and_exchange_bool_acq (&__fork_handlers->refcntr, - oldval + 1, oldval)) - /* The value changed, try again. */ - continue; - - /* We bumped the reference counter for the first entry in the - list. That means that none of the following entries will - just go away. The unloading code works in the order of the - list. - - While executing the registered handlers we are building a - list of all the entries so that we can go backward later on. */ - while (1) - { - /* Execute the handler if there is one. */ - if (runp->prepare_handler != NULL) - runp->prepare_handler (); - - /* Create a new element for the list. */ - struct used_handler *newp - = (struct used_handler *) alloca (sizeof (*newp)); - newp->handler = runp; - newp->next = allp; - allp = newp; - - /* Advance to the next handler. */ - runp = runp->next; - if (runp == NULL) - break; - - /* Bump the reference counter for the next entry. */ - atomic_increment (&runp->refcntr); - } - - /* We are done. */ - break; - } - - _IO_list_lock (); - -#ifndef NDEBUG - pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid); -#endif - - /* We need to prevent the getpid() code to update the PID field so - that, if a signal arrives in the child very early and the signal - handler uses getpid(), the value returned is correct. */ - pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid); - THREAD_SETMEM (THREAD_SELF, pid, -parentpid); - -#ifdef ARCH_FORK - pid = ARCH_FORK (); -#else -# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used" - pid = INLINE_SYSCALL (fork, 0); -#endif - - - if (pid == 0) - { - struct pthread *self = THREAD_SELF; - - assert (THREAD_GETMEM (self, tid) != ppid); - - if (__fork_generation_pointer != NULL) - *__fork_generation_pointer += 4; - - /* Adjust the PID field for the new process. */ - THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid)); - -#if HP_TIMING_AVAIL - /* The CPU clock of the thread and process have to be set to zero. */ - hp_timing_t now; - HP_TIMING_NOW (now); - THREAD_SETMEM (self, cpuclock_offset, now); - GL(dl_cpuclock_offset) = now; -#endif - -#ifdef __NR_set_robust_list - /* Initialize the robust mutex list which has been reset during - the fork. We do not check for errors since if it fails here - it failed at process start as well and noone could have used - robust mutexes. We also do not have to set - self->robust_head.futex_offset since we inherit the correct - value from the parent. */ -# ifdef SHARED - if (__builtin_expect (__libc_pthread_functions_init, 0)) - PTHFCT_CALL (ptr_set_robust, (self)); -# else - extern __typeof (__nptl_set_robust) __nptl_set_robust - __attribute__((weak)); - if (__builtin_expect (__nptl_set_robust != NULL, 0)) - __nptl_set_robust (self); -# endif -#endif - - /* Reset the file list. These are recursive mutexes. */ - fresetlockfiles (); - - /* Reset locks in the I/O code. */ - _IO_list_resetlock (); - - /* Reset the lock the dynamic loader uses to protect its data. */ - __rtld_lock_initialize (GL(dl_load_lock)); - - /* Run the handlers registered for the child. */ - while (allp != NULL) - { - if (allp->handler->child_handler != NULL) - allp->handler->child_handler (); - - /* Note that we do not have to wake any possible waiter. - This is the only thread in the new process. The count - may have been bumped up by other threads doing a fork. - We reset it to 1, to avoid waiting for non-existing - thread(s) to release the count. */ - allp->handler->refcntr = 1; - - /* XXX We could at this point look through the object pool - and mark all objects not on the __fork_handlers list as - unused. This is necessary in case the fork() happened - while another thread called dlclose() and that call had - to create a new list. */ - - allp = allp->next; - } - - /* Initialize the fork lock. */ - __fork_lock = LLL_LOCK_INITIALIZER; - } - else - { - assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid); - - /* Restore the PID value. */ - THREAD_SETMEM (THREAD_SELF, pid, parentpid); - - /* We execute this even if the 'fork' call failed. */ - _IO_list_unlock (); - - /* Run the handlers registered for the parent. */ - while (allp != NULL) - { - if (allp->handler->parent_handler != NULL) - allp->handler->parent_handler (); - - if (atomic_decrement_and_test (&allp->handler->refcntr) - && allp->handler->need_signal) - lll_futex_wake (allp->handler->refcntr, 1, LLL_PRIVATE); - - allp = allp->next; - } - } - - return pid; -} -weak_alias (__libc_fork, __fork) -libc_hidden_def (__fork) -weak_alias (__libc_fork, fork) diff --git a/nptl/sysdeps/unix/sysv/linux/fork.h b/nptl/sysdeps/unix/sysv/linux/fork.h deleted file mode 100644 index 8e28a76098..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/fork.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include - -/* The fork generation counter, defined in libpthread. */ -extern unsigned long int __fork_generation attribute_hidden; - -/* Pointer to the fork generation counter in the thread library. */ -extern unsigned long int *__fork_generation_pointer attribute_hidden; - -/* Lock to protect allocation and deallocation of fork handlers. */ -extern int __fork_lock attribute_hidden; - -/* Elements of the fork handler lists. */ -struct fork_handler -{ - struct fork_handler *next; - void (*prepare_handler) (void); - void (*parent_handler) (void); - void (*child_handler) (void); - void *dso_handle; - unsigned int refcntr; - int need_signal; -}; - -/* The single linked list of all currently registered for handlers. */ -extern struct fork_handler *__fork_handlers attribute_hidden; - - -/* Function to call to unregister fork handlers. */ -extern void __unregister_atfork (void *dso_handle) attribute_hidden; -#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle) - - -/* C library side function to register new fork handlers. */ -extern int __register_atfork (void (*__prepare) (void), - void (*__parent) (void), - void (*__child) (void), - void *dso_handle); -libc_hidden_proto (__register_atfork) - -/* Add a new element to the fork list. */ -extern void __linkin_atfork (struct fork_handler *newp) attribute_hidden; diff --git a/nptl/sysdeps/unix/sysv/linux/getpid.c b/nptl/sysdeps/unix/sysv/linux/getpid.c deleted file mode 100644 index 937b1d4e11..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/getpid.c +++ /dev/null @@ -1,64 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see - . */ - -#include -#include -#include - - -#ifndef NOT_IN_libc -static inline __attribute__((always_inline)) pid_t really_getpid (pid_t oldval); - -static inline __attribute__((always_inline)) pid_t -really_getpid (pid_t oldval) -{ - if (__glibc_likely (oldval == 0)) - { - pid_t selftid = THREAD_GETMEM (THREAD_SELF, tid); - if (__glibc_likely (selftid != 0)) - return selftid; - } - - INTERNAL_SYSCALL_DECL (err); - pid_t result = INTERNAL_SYSCALL (getpid, err, 0); - - /* We do not set the PID field in the TID here since we might be - called from a signal handler while the thread executes fork. */ - if (oldval == 0) - THREAD_SETMEM (THREAD_SELF, tid, result); - return result; -} -#endif - -pid_t -__getpid (void) -{ -#ifdef NOT_IN_libc - INTERNAL_SYSCALL_DECL (err); - pid_t result = INTERNAL_SYSCALL (getpid, err, 0); -#else - pid_t result = THREAD_GETMEM (THREAD_SELF, pid); - if (__glibc_unlikely (result <= 0)) - result = really_getpid (result); -#endif - return result; -} - -libc_hidden_def (__getpid) -weak_alias (__getpid, getpid) -libc_hidden_def (getpid) diff --git a/nptl/sysdeps/unix/sysv/linux/internaltypes.h b/nptl/sysdeps/unix/sysv/linux/internaltypes.h deleted file mode 100644 index d127f688cf..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/internaltypes.h +++ /dev/null @@ -1,161 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#ifndef _INTERNALTYPES_H -#define _INTERNALTYPES_H 1 - -#include - - -struct pthread_attr -{ - /* Scheduler parameters and priority. */ - struct sched_param schedparam; - int schedpolicy; - /* Various flags like detachstate, scope, etc. */ - int flags; - /* Size of guard area. */ - size_t guardsize; - /* Stack handling. */ - void *stackaddr; - size_t stacksize; - /* Affinity map. */ - cpu_set_t *cpuset; - size_t cpusetsize; -}; - -#define ATTR_FLAG_DETACHSTATE 0x0001 -#define ATTR_FLAG_NOTINHERITSCHED 0x0002 -#define ATTR_FLAG_SCOPEPROCESS 0x0004 -#define ATTR_FLAG_STACKADDR 0x0008 -#define ATTR_FLAG_OLDATTR 0x0010 -#define ATTR_FLAG_SCHED_SET 0x0020 -#define ATTR_FLAG_POLICY_SET 0x0040 - - -/* Mutex attribute data structure. */ -struct pthread_mutexattr -{ - /* Identifier for the kind of mutex. - - Bit 31 is set if the mutex is to be shared between processes. - - Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify - the type of the mutex. */ - int mutexkind; -}; - - -/* Conditional variable attribute data structure. */ -struct pthread_condattr -{ - /* Combination of values: - - Bit 0 : flag whether conditional variable will be sharable between - processes. - - Bit 1-7: clock ID. */ - int value; -}; - - -/* The __NWAITERS field is used as a counter and to house the number - of bits for other purposes. COND_CLOCK_BITS is the number - of bits needed to represent the ID of the clock. COND_NWAITERS_SHIFT - is the number of bits reserved for other purposes like the clock. */ -#define COND_CLOCK_BITS 1 -#define COND_NWAITERS_SHIFT 1 - - -/* Read-write lock variable attribute data structure. */ -struct pthread_rwlockattr -{ - int lockkind; - int pshared; -}; - - -/* Barrier data structure. */ -struct pthread_barrier -{ - unsigned int curr_event; - int lock; - unsigned int left; - unsigned int init_count; - int private; -}; - - -/* Barrier variable attribute data structure. */ -struct pthread_barrierattr -{ - int pshared; -}; - - -/* Thread-local data handling. */ -struct pthread_key_struct -{ - /* Sequence numbers. Even numbers indicated vacant entries. Note - that zero is even. We use uintptr_t to not require padding on - 32- and 64-bit machines. On 64-bit machines it helps to avoid - wrapping, too. */ - uintptr_t seq; - - /* Destructor for the data. */ - void (*destr) (void *); -}; - -/* Check whether an entry is unused. */ -#define KEY_UNUSED(p) (((p) & 1) == 0) -/* Check whether a key is usable. We cannot reuse an allocated key if - the sequence counter would overflow after the next destroy call. - This would mean that we potentially free memory for a key with the - same sequence. This is *very* unlikely to happen, A program would - have to create and destroy a key 2^31 times (on 32-bit platforms, - on 64-bit platforms that would be 2^63). If it should happen we - simply don't use this specific key anymore. */ -#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2))) - - -/* Handling of read-write lock data. */ -// XXX For now there is only one flag. Maybe more in future. -#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0) - - -/* Semaphore variable structure. */ -struct new_sem -{ - unsigned int value; - int private; - unsigned long int nwaiters; -}; - -struct old_sem -{ - unsigned int value; -}; - - -/* Compatibility type for old conditional variable interfaces. */ -typedef struct -{ - pthread_cond_t *cond; -} pthread_cond_2_0_t; - -#endif /* internaltypes.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c b/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c deleted file mode 100644 index b3a960c980..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/jmp-unwind.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Clean up stack frames unwound by longjmp. Linux version. - Copyright (C) 1995-2014 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; if not, see - . */ - -#include -#include -#include - -extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); -#pragma weak __pthread_cleanup_upto - - -void -_longjmp_unwind (jmp_buf env, int val) -{ -#ifdef SHARED - if (__libc_pthread_functions_init) - PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, - CURRENT_STACK_FRAME)); -#else - if (__pthread_cleanup_upto != NULL) - __pthread_cleanup_upto (env->__jmpbuf, CURRENT_STACK_FRAME); -#endif -} diff --git a/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h b/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h deleted file mode 100644 index 532da55e14..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/kernel-posix-timers.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see . */ - -#include -#include -#include -#include - - -/* Nonzero if the system calls are not available. */ -extern int __no_posix_timers attribute_hidden; - -/* Callback to start helper thread. */ -extern void __start_helper_thread (void) attribute_hidden; - -/* Control variable for helper thread creation. */ -extern pthread_once_t __helper_once attribute_hidden; - -/* TID of the helper thread. */ -extern pid_t __helper_tid attribute_hidden; - -/* List of active SIGEV_THREAD timers. */ -extern struct timer *__active_timer_sigev_thread attribute_hidden; -/* Lock for the __active_timer_sigev_thread. */ -extern pthread_mutex_t __active_timer_sigev_thread_lock attribute_hidden; - - -/* Type of timers in the kernel. */ -typedef int kernel_timer_t; - - -/* Internal representation of timer. */ -struct timer -{ - /* Notification mechanism. */ - int sigev_notify; - - /* Timer ID returned by the kernel. */ - kernel_timer_t ktimerid; - - /* All new elements must be added after ktimerid. And if the thrfunc - element is not the third element anymore the memory allocation in - timer_create needs to be changed. */ - - /* Parameters for the thread to be started for SIGEV_THREAD. */ - void (*thrfunc) (sigval_t); - sigval_t sival; - pthread_attr_t attr; - - /* Next element in list of active SIGEV_THREAD timers. */ - struct timer *next; -}; diff --git a/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c deleted file mode 100644 index 080d4bdafb..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/libc-lowlevellock.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - 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, see - . */ - -/* No difference to lowlevellock.c, except we lose a couple of functions. */ -#include diff --git a/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c b/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c deleted file mode 100644 index acf3594d71..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/libc_multiple_threads.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include - -#ifndef NOT_IN_libc -# ifndef TLS_MULTIPLE_THREADS_IN_TCB -/* Variable set to a nonzero value either if more than one thread runs or ran, - or if a single-threaded process is trying to cancel itself. See - nptl/descr.h for more context on the single-threaded process case. */ -int __libc_multiple_threads attribute_hidden; -# endif -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c deleted file mode 100644 index 4d8d710cca..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef TLS_MULTIPLE_THREADS_IN_TCB -void -#else -extern int __libc_multiple_threads attribute_hidden; - -int * -#endif -__libc_pthread_init (ptr, reclaim, functions) - unsigned long int *ptr; - void (*reclaim) (void); - const struct pthread_functions *functions; -{ - /* Remember the pointer to the generation counter in libpthread. */ - __fork_generation_pointer = ptr; - - /* Called by a child after fork. */ - __register_atfork (NULL, NULL, reclaim, NULL); - -#ifdef SHARED - /* Copy the function pointers into an array in libc. This enables - access with just one memory reference but moreso, it prevents - hijacking the function pointers with just one pointer change. We - "encrypt" the function pointers since we cannot write-protect the - array easily enough. */ - union ptrhack - { - struct pthread_functions pf; -# define NPTRS (sizeof (struct pthread_functions) / sizeof (void *)) - void *parr[NPTRS]; - } __attribute__ ((may_alias)) const *src; - union ptrhack *dest; - - src = (const void *) functions; - dest = (void *) &__libc_pthread_functions; - - for (size_t cnt = 0; cnt < NPTRS; ++cnt) - { - void *p = src->parr[cnt]; - PTR_MANGLE (p); - dest->parr[cnt] = p; - } - __libc_pthread_functions_init = 1; -#endif - -#ifndef TLS_MULTIPLE_THREADS_IN_TCB - return &__libc_multiple_threads; -#endif -} - -#ifdef SHARED -libc_freeres_fn (freeres_libptread) -{ - if (__libc_pthread_functions_init) - PTHFCT_CALL (ptr_freeres, ()); -} -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym deleted file mode 100644 index cfe22b0892..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelbarrier.sym +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include "internaltypes.h" - --- - -CURR_EVENT offsetof (struct pthread_barrier, curr_event) -MUTEX offsetof (struct pthread_barrier, lock) -LEFT offsetof (struct pthread_barrier, left) -INIT_COUNT offsetof (struct pthread_barrier, init_count) -PRIVATE offsetof (struct pthread_barrier, private) diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym deleted file mode 100644 index 18e1adad43..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelcond.sym +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -#include -#include - --- - -cond_lock offsetof (pthread_cond_t, __data.__lock) -cond_futex offsetof (pthread_cond_t, __data.__futex) -cond_nwaiters offsetof (pthread_cond_t, __data.__nwaiters) -total_seq offsetof (pthread_cond_t, __data.__total_seq) -wakeup_seq offsetof (pthread_cond_t, __data.__wakeup_seq) -woken_seq offsetof (pthread_cond_t, __data.__woken_seq) -dep_mutex offsetof (pthread_cond_t, __data.__mutex) -broadcast_seq offsetof (pthread_cond_t, __data.__broadcast_seq) -nwaiters_shift COND_NWAITERS_SHIFT diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevellock.c b/nptl/sysdeps/unix/sysv/linux/lowlevellock.c deleted file mode 100644 index e198af7e8d..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/lowlevellock.c +++ /dev/null @@ -1,124 +0,0 @@ -/* low level locking for pthread library. Generic futex-using version. - Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include - -void -__lll_lock_wait_private (int *futex) -{ - if (*futex == 2) - lll_futex_wait (futex, 2, LLL_PRIVATE); - - while (atomic_exchange_acq (futex, 2) != 0) - lll_futex_wait (futex, 2, LLL_PRIVATE); -} - - -/* These functions don't get included in libc.so */ -#ifdef IS_IN_libpthread -void -__lll_lock_wait (int *futex, int private) -{ - if (*futex == 2) - lll_futex_wait (futex, 2, private); - - while (atomic_exchange_acq (futex, 2) != 0) - lll_futex_wait (futex, 2, private); -} - - -int -__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private) -{ - /* Reject invalid timeouts. */ - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) - return EINVAL; - - /* Try locking. */ - while (atomic_exchange_acq (futex, 2) != 0) - { - struct timeval tv; - - /* Get the current time. */ - (void) __gettimeofday (&tv, NULL); - - /* Compute relative timeout. */ - struct timespec rt; - rt.tv_sec = abstime->tv_sec - tv.tv_sec; - rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; - if (rt.tv_nsec < 0) - { - rt.tv_nsec += 1000000000; - --rt.tv_sec; - } - - if (rt.tv_sec < 0) - return ETIMEDOUT; - - /* Wait. */ - lll_futex_timed_wait (futex, 2, &rt, private); - } - - return 0; -} - - -int -__lll_timedwait_tid (int *tidp, const struct timespec *abstime) -{ - int tid; - - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) - return EINVAL; - - /* Repeat until thread terminated. */ - while ((tid = *tidp) != 0) - { - struct timeval tv; - struct timespec rt; - - /* Get the current time. */ - (void) __gettimeofday (&tv, NULL); - - /* Compute relative timeout. */ - rt.tv_sec = abstime->tv_sec - tv.tv_sec; - rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; - if (rt.tv_nsec < 0) - { - rt.tv_nsec += 1000000000; - --rt.tv_sec; - } - - /* Already timed out? */ - if (rt.tv_sec < 0) - return ETIMEDOUT; - - /* Wait until thread terminates. The kernel so far does not use - the private futex operations for this. */ - if (lll_futex_timed_wait (tidp, tid, &rt, LLL_SHARED) == -ETIMEDOUT) - return ETIMEDOUT; - } - - return 0; -} -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c deleted file mode 100644 index 35258071cf..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c +++ /dev/null @@ -1,128 +0,0 @@ -/* Copyright (C) 2006-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek , 2006. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include - - -int -__lll_robust_lock_wait (int *futex, int private) -{ - int oldval = *futex; - int tid = THREAD_GETMEM (THREAD_SELF, tid); - - /* If the futex changed meanwhile try locking again. */ - if (oldval == 0) - goto try; - - do - { - if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED)) - return oldval; - - int newval = oldval | FUTEX_WAITERS; - if (oldval != newval - && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) - continue; - - lll_futex_wait (futex, newval, private); - - try: - ; - } - while ((oldval = atomic_compare_and_exchange_val_acq (futex, - tid | FUTEX_WAITERS, - 0)) != 0); - return 0; -} - - -int -__lll_robust_timedlock_wait (int *futex, const struct timespec *abstime, - int private) -{ - /* Reject invalid timeouts. */ - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) - return EINVAL; - - int tid = THREAD_GETMEM (THREAD_SELF, tid); - int oldval = *futex; - - /* If the futex changed meanwhile try locking again. */ - if (oldval == 0) - goto try; - - /* Work around the fact that the kernel rejects negative timeout values - despite them being valid. */ - if (__glibc_unlikely (abstime->tv_sec < 0)) - return ETIMEDOUT; - - do - { -#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ - || !defined lll_futex_timed_wait_bitset) - struct timeval tv; - struct timespec rt; - - /* Get the current time. */ - (void) __gettimeofday (&tv, NULL); - - /* Compute relative timeout. */ - rt.tv_sec = abstime->tv_sec - tv.tv_sec; - rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; - if (rt.tv_nsec < 0) - { - rt.tv_nsec += 1000000000; - --rt.tv_sec; - } - - /* Already timed out? */ - if (rt.tv_sec < 0) - return ETIMEDOUT; -#endif - - /* Wait. */ - if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED)) - return oldval; - - int newval = oldval | FUTEX_WAITERS; - if (oldval != newval - && atomic_compare_and_exchange_bool_acq (futex, newval, oldval)) - continue; - -#if (!defined __ASSUME_FUTEX_CLOCK_REALTIME \ - || !defined lll_futex_timed_wait_bitset) - lll_futex_timed_wait (futex, newval, &rt, private); -#else - lll_futex_timed_wait_bitset (futex, newval, abstime, - FUTEX_CLOCK_REALTIME, private); -#endif - - try: - ; - } - while ((oldval = atomic_compare_and_exchange_val_acq (futex, - tid | FUTEX_WAITERS, - 0)) != 0); - - return 0; -} diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym deleted file mode 100644 index 2f1e9da52b..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.sym +++ /dev/null @@ -1,6 +0,0 @@ -#include -#include - --- - -TID offsetof (struct pthread, tid) diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym b/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym deleted file mode 100644 index f50b25bfb8..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelrwlock.sym +++ /dev/null @@ -1,16 +0,0 @@ -#include -#include -#include -#include - --- - -MUTEX offsetof (pthread_rwlock_t, __data.__lock) -NR_READERS offsetof (pthread_rwlock_t, __data.__nr_readers) -READERS_WAKEUP offsetof (pthread_rwlock_t, __data.__readers_wakeup) -WRITERS_WAKEUP offsetof (pthread_rwlock_t, __data.__writer_wakeup) -READERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_readers_queued) -WRITERS_QUEUED offsetof (pthread_rwlock_t, __data.__nr_writers_queued) -FLAGS offsetof (pthread_rwlock_t, __data.__flags) -WRITER offsetof (pthread_rwlock_t, __data.__writer) -PSHARED offsetof (pthread_rwlock_t, __data.__shared) diff --git a/nptl/sysdeps/unix/sysv/linux/mq_notify.c b/nptl/sysdeps/unix/sysv/linux/mq_notify.c deleted file mode 100644 index d50a9f2d57..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/mq_notify.c +++ /dev/null @@ -1,282 +0,0 @@ -/* Copyright (C) 2004-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contribute by Ulrich Drepper , 2004. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#ifdef __NR_mq_notify - -/* Defined in the kernel headers: */ -#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */ -#define NOTIFY_WOKENUP 1 /* Code for notifcation. */ -#define NOTIFY_REMOVED 2 /* Code for closed message queue - of de-notifcation. */ - - -/* Data structure for the queued notification requests. */ -union notify_data -{ - struct - { - void (*fct) (union sigval); /* The function to run. */ - union sigval param; /* The parameter to pass. */ - pthread_attr_t *attr; /* Attributes to create the thread with. */ - /* NB: on 64-bit machines the struct as a size of 24 bytes. Which means - byte 31 can still be used for returning the status. */ - }; - char raw[NOTIFY_COOKIE_LEN]; -}; - - -/* Keep track of the initialization. */ -static pthread_once_t once = PTHREAD_ONCE_INIT; - - -/* The netlink socket. */ -static int netlink_socket = -1; - - -/* Barrier used to make sure data passed to the new thread is not - resused by the parent. */ -static pthread_barrier_t notify_barrier; - - -/* Modify the signal mask. We move this into a separate function so - that the stack space needed for sigset_t is not deducted from what - the thread can use. */ -static int -__attribute__ ((noinline)) -change_sigmask (int how, sigset_t *oss) -{ - sigset_t ss; - sigfillset (&ss); - return pthread_sigmask (how, &ss, oss); -} - - -/* The function used for the notification. */ -static void * -notification_function (void *arg) -{ - /* Copy the function and parameter so that the parent thread can go - on with its life. */ - volatile union notify_data *data = (volatile union notify_data *) arg; - void (*fct) (union sigval) = data->fct; - union sigval param = data->param; - - /* Let the parent go. */ - (void) pthread_barrier_wait (¬ify_barrier); - - /* Make the thread detached. */ - (void) pthread_detach (pthread_self ()); - - /* The parent thread has all signals blocked. This is probably a - bit surprising for this thread. So we unblock all of them. */ - (void) change_sigmask (SIG_UNBLOCK, NULL); - - /* Now run the user code. */ - fct (param); - - /* And we are done. */ - return NULL; -} - - -/* Helper thread. */ -static void * -helper_thread (void *arg) -{ - while (1) - { - union notify_data data; - - ssize_t n = recv (netlink_socket, &data, sizeof (data), - MSG_NOSIGNAL | MSG_WAITALL); - if (n < NOTIFY_COOKIE_LEN) - continue; - - if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) - { - /* Just create the thread as instructed. There is no way to - report a problem with creating a thread. */ - pthread_t th; - if (__builtin_expect (pthread_create (&th, data.attr, - notification_function, &data) - == 0, 0)) - /* Since we passed a pointer to DATA to the new thread we have - to wait until it is done with it. */ - (void) pthread_barrier_wait (¬ify_barrier); - } - else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) - /* The only state we keep is the copy of the thread attributes. */ - free (data.attr); - } - return NULL; -} - - -static void -reset_once (void) -{ - once = PTHREAD_ONCE_INIT; -} - - -static void -init_mq_netlink (void) -{ - /* This code might be called a second time after fork(). The file - descriptor is inherited from the parent. */ - if (netlink_socket == -1) - { - /* Just a normal netlink socket, not bound. */ - netlink_socket = socket (AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, 0); - /* No need to do more if we have no socket. */ - if (netlink_socket == -1) - return; - } - - int err = 1; - - /* Initialize the barrier. */ - if (__builtin_expect (pthread_barrier_init (¬ify_barrier, NULL, 2) == 0, - 0)) - { - /* Create the helper thread. */ - pthread_attr_t attr; - (void) pthread_attr_init (&attr); - (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); - /* We do not need much stack space, the bare minimum will be enough. */ - (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); - - /* Temporarily block all signals so that the newly created - thread inherits the mask. */ - sigset_t oss; - int have_no_oss = change_sigmask (SIG_BLOCK, &oss); - - pthread_t th; - err = pthread_create (&th, &attr, helper_thread, NULL); - - /* Reset the signal mask. */ - if (!have_no_oss) - pthread_sigmask (SIG_SETMASK, &oss, NULL); - - (void) pthread_attr_destroy (&attr); - - if (err == 0) - { - static int added_atfork; - - if (added_atfork == 0 - && pthread_atfork (NULL, NULL, reset_once) != 0) - { - /* The child thread will call recv() which is a - cancellation point. */ - (void) pthread_cancel (th); - err = 1; - } - else - added_atfork = 1; - } - } - - if (err != 0) - { - close_not_cancel_no_status (netlink_socket); - netlink_socket = -1; - } -} - - -/* Register notification upon message arrival to an empty message queue - MQDES. */ -int -mq_notify (mqd_t mqdes, const struct sigevent *notification) -{ - /* Make sure the type is correctly defined. */ - assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN); - - /* Special treatment needed for SIGEV_THREAD. */ - if (notification == NULL || notification->sigev_notify != SIGEV_THREAD) - return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); - - /* The kernel cannot directly start threads. This will have to be - done at userlevel. Since we cannot start threads from signal - handlers we have to create a dedicated thread which waits for - notifications for arriving messages and creates threads in - response. */ - - /* Initialize only once. */ - pthread_once (&once, init_mq_netlink); - - /* If we cannot create the netlink socket we cannot provide - SIGEV_THREAD support. */ - if (__glibc_unlikely (netlink_socket == -1)) - { - __set_errno (ENOSYS); - return -1; - } - - /* Create the cookie. It will hold almost all the state. */ - union notify_data data; - memset (&data, '\0', sizeof (data)); - data.fct = notification->sigev_notify_function; - data.param = notification->sigev_value; - - if (notification->sigev_notify_attributes != NULL) - { - /* The thread attribute has to be allocated separately. */ - data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t)); - if (data.attr == NULL) - return -1; - - memcpy (data.attr, notification->sigev_notify_attributes, - sizeof (pthread_attr_t)); - } - - /* Construct the new request. */ - struct sigevent se; - se.sigev_notify = SIGEV_THREAD; - se.sigev_signo = netlink_socket; - se.sigev_value.sival_ptr = &data; - - /* Tell the kernel. */ - int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); - - /* If it failed, free the allocated memory. */ - if (__glibc_unlikely (retval != 0)) - free (data.attr); - - return retval; -} - -#else -# include -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/pt-fork.c b/nptl/sysdeps/unix/sysv/linux/pt-fork.c deleted file mode 100644 index 582409486e..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pt-fork.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include - - -pid_t -__fork (void) -{ - return __libc_fork (); -} -strong_alias (__fork, fork) diff --git a/nptl/sysdeps/unix/sysv/linux/pt-raise.c b/nptl/sysdeps/unix/sysv/linux/pt-raise.c deleted file mode 100644 index fc26e858b3..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pt-raise.c +++ /dev/null @@ -1,38 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include -#include -#include -#include - - -int -raise (sig) - int sig; -{ - /* raise is an async-safe function. It could be called while the - fork function temporarily invalidated the PID field. Adjust for - that. */ - pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); - if (__glibc_unlikely (pid < 0)) - pid = -pid; - - return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), - sig); -} diff --git a/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym b/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym deleted file mode 100644 index 0ac51dba98..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread-pi-defines.sym +++ /dev/null @@ -1,9 +0,0 @@ -#include - --- These PI macros are used by assembly code. - -MUTEX_KIND offsetof (pthread_mutex_t, __data.__kind) -ROBUST_BIT PTHREAD_MUTEX_ROBUST_NORMAL_NP -PI_BIT PTHREAD_MUTEX_PRIO_INHERIT_NP -PS_BIT PTHREAD_MUTEX_PSHARED_BIT -TID_MASK FUTEX_TID_MASK diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c b/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c deleted file mode 100644 index c80fef47c4..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_attr_getaffinity.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -int -__pthread_attr_getaffinity_new (const pthread_attr_t *attr, size_t cpusetsize, - cpu_set_t *cpuset) -{ - const struct pthread_attr *iattr; - - assert (sizeof (*attr) >= sizeof (struct pthread_attr)); - iattr = (const struct pthread_attr *) attr; - - if (iattr->cpuset != NULL) - { - /* Check whether there are any bits set beyond the limits - the user requested. */ - for (size_t cnt = cpusetsize; cnt < iattr->cpusetsize; ++cnt) - if (((char *) iattr->cpuset)[cnt] != 0) - return EINVAL; - - /* Copy over the cpuset from the thread attribute object. Limit the copy - to the minimum of the source and destination sizes to prevent a buffer - overrun. If the destination is larger, fill the remaining space with - zeroes. */ - void *p = mempcpy (cpuset, iattr->cpuset, - MIN (iattr->cpusetsize, cpusetsize)); - if (cpusetsize > iattr->cpusetsize) - memset (p, '\0', cpusetsize - iattr->cpusetsize); - } - else - /* We have no information. */ - memset (cpuset, -1, cpusetsize); - - return 0; -} -versioned_symbol (libpthread, __pthread_attr_getaffinity_new, - pthread_attr_getaffinity_np, GLIBC_2_3_4); - - -#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) -int -__pthread_attr_getaffinity_old (const pthread_attr_t *attr, cpu_set_t *cpuset) -{ - /* The old interface by default assumed a 1024 processor bitmap. */ - return __pthread_attr_getaffinity_new (attr, 128, cpuset); -} -compat_symbol (libpthread, __pthread_attr_getaffinity_old, - pthread_attr_getaffinity_np, GLIBC_2_3_3); -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c b/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c deleted file mode 100644 index 96c52ea531..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_attr_setaffinity.c +++ /dev/null @@ -1,80 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include -#include - - - - -int -__pthread_attr_setaffinity_new (pthread_attr_t *attr, size_t cpusetsize, - const cpu_set_t *cpuset) -{ - struct pthread_attr *iattr; - - assert (sizeof (*attr) >= sizeof (struct pthread_attr)); - iattr = (struct pthread_attr *) attr; - - if (cpuset == NULL || cpusetsize == 0) - { - free (iattr->cpuset); - iattr->cpuset = NULL; - iattr->cpusetsize = 0; - } - else - { - int ret = check_cpuset_attr (cpuset, cpusetsize); - - if (ret) - return ret; - - if (iattr->cpusetsize != cpusetsize) - { - void *newp = (cpu_set_t *) realloc (iattr->cpuset, cpusetsize); - if (newp == NULL) - return ENOMEM; - - iattr->cpuset = newp; - iattr->cpusetsize = cpusetsize; - } - - memcpy (iattr->cpuset, cpuset, cpusetsize); - } - - return 0; -} -versioned_symbol (libpthread, __pthread_attr_setaffinity_new, - pthread_attr_setaffinity_np, GLIBC_2_3_4); - - -#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) -int -__pthread_attr_setaffinity_old (pthread_attr_t *attr, cpu_set_t *cpuset) -{ - /* The old interface by default assumed a 1024 processor bitmap. */ - return __pthread_attr_setaffinity_new (attr, 128, cpuset); -} -compat_symbol (libpthread, __pthread_attr_setaffinity_old, - pthread_attr_setaffinity_np, GLIBC_2_3_3); -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c b/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c deleted file mode 100644 index f58e9cc3e9..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_getaffinity.c +++ /dev/null @@ -1,59 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include -#include -#include - - -int -__pthread_getaffinity_new (pthread_t th, size_t cpusetsize, cpu_set_t *cpuset) -{ - const struct pthread *pd = (const struct pthread *) th; - - INTERNAL_SYSCALL_DECL (err); - int res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, pd->tid, - MIN (INT_MAX, cpusetsize), cpuset); - if (INTERNAL_SYSCALL_ERROR_P (res, err)) - return INTERNAL_SYSCALL_ERRNO (res, err); - - /* Clean the rest of the memory the kernel didn't do. */ - memset ((char *) cpuset + res, '\0', cpusetsize - res); - - return 0; -} -strong_alias (__pthread_getaffinity_new, __pthread_getaffinity_np) -versioned_symbol (libpthread, __pthread_getaffinity_new, - pthread_getaffinity_np, GLIBC_2_3_4); - - -#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) -int -__pthread_getaffinity_old (pthread_t th, cpu_set_t *cpuset) -{ - /* The old interface by default assumed a 1024 processor bitmap. */ - return __pthread_getaffinity_new (th, 128, cpuset); -} -compat_symbol (libpthread, __pthread_getaffinity_old, pthread_getaffinity_np, - GLIBC_2_3_3); -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c b/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c deleted file mode 100644 index 3e634a03c8..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c +++ /dev/null @@ -1,44 +0,0 @@ -/* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t. Linux version - Copyright (C) 2000-2014 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, see . */ - -#include -#include -#include -#include -#include - - -int -pthread_getcpuclockid (threadid, clockid) - pthread_t threadid; - clockid_t *clockid; -{ - struct pthread *pd = (struct pthread *) threadid; - - /* Make sure the descriptor is valid. */ - if (INVALID_TD_P (pd)) - /* Not a valid thread handle. */ - return ESRCH; - - /* The clockid_t value is a simple computation from the TID. */ - - const clockid_t tidclock = MAKE_THREAD_CPUCLOCK (pd->tid, CPUCLOCK_SCHED); - - *clockid = tidclock; - return 0; -} diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_getname.c b/nptl/sysdeps/unix/sysv/linux/pthread_getname.c deleted file mode 100644 index e5a319a3e1..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_getname.c +++ /dev/null @@ -1,72 +0,0 @@ -/* pthread_getname_np -- Get thread name. Linux version - Copyright (C) 2010-2014 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, see . */ - -#include -#include -#include -#include -#include -#include -#include - -#include - - -int -pthread_getname_np (th, buf, len) - pthread_t th; - char *buf; - size_t len; -{ - const struct pthread *pd = (const struct pthread *) th; - - /* Unfortunately the kernel headers do not export the TASK_COMM_LEN - macro. So we have to define it here. */ -#define TASK_COMM_LEN 16 - if (len < TASK_COMM_LEN) - return ERANGE; - - if (pd == THREAD_SELF) - return prctl (PR_GET_NAME, buf) ? errno : 0; - -#define FMT "/proc/self/task/%u/comm" - char fname[sizeof (FMT) + 8]; - sprintf (fname, FMT, (unsigned int) pd->tid); - - int fd = open_not_cancel_2 (fname, O_RDONLY); - if (fd == -1) - return errno; - - int res = 0; - ssize_t n = TEMP_FAILURE_RETRY (read_not_cancel (fd, buf, len)); - if (n < 0) - res = errno; - else - { - if (buf[n - 1] == '\n') - buf[n - 1] = '\0'; - else if (n == len) - res = ERANGE; - else - buf[n] = '\0'; - } - - close_not_cancel_no_status (fd); - - return res; -} diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c b/nptl/sysdeps/unix/sysv/linux/pthread_kill.c deleted file mode 100644 index 0a4d8627a9..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_kill.c +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include -#include -#include -#include -#include - - -int -__pthread_kill (threadid, signo) - pthread_t threadid; - int signo; -{ - struct pthread *pd = (struct pthread *) threadid; - - /* Make sure the descriptor is valid. */ - if (DEBUGGING_P && INVALID_TD_P (pd)) - /* Not a valid thread handle. */ - return ESRCH; - - /* Force load of pd->tid into local variable or register. Otherwise - if a thread exits between ESRCH test and tgkill, we might return - EINVAL, because pd->tid would be cleared by the kernel. */ - pid_t tid = atomic_forced_read (pd->tid); - if (__glibc_unlikely (tid <= 0)) - /* Not a valid thread handle. */ - return ESRCH; - - /* Disallow sending the signal we use for cancellation, timers, - for the setxid implementation. */ - if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) - return EINVAL; - - /* We have a special syscall to do the work. */ - INTERNAL_SYSCALL_DECL (err); - - /* One comment: The PID field in the TCB can temporarily be changed - (in fork). But this must not affect this code here. Since this - function would have to be called while the thread is executing - fork, it would have to happen in a signal handler. But this is - no allowed, pthread_kill is not guaranteed to be async-safe. */ - int val; - val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), - tid, signo); - - return (INTERNAL_SYSCALL_ERROR_P (val, err) - ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); -} -strong_alias (__pthread_kill, pthread_kill) diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c b/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c deleted file mode 100644 index 7b6fbc18aa..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c +++ /dev/null @@ -1,21 +0,0 @@ -#include - -#define LLL_MUTEX_LOCK(mutex) \ - lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)) - -/* Not actually elided so far. Needed? */ -#define LLL_MUTEX_LOCK_ELISION(mutex) \ - ({ lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)); 0; }) - -#define LLL_MUTEX_TRYLOCK(mutex) \ - lll_cond_trylock ((mutex)->__data.__lock) -#define LLL_MUTEX_TRYLOCK_ELISION(mutex) LLL_MUTEX_TRYLOCK(mutex) - -#define LLL_ROBUST_MUTEX_LOCK(mutex, id) \ - lll_robust_cond_lock ((mutex)->__data.__lock, id, \ - PTHREAD_ROBUST_MUTEX_PSHARED (mutex)) -#define __pthread_mutex_lock __pthread_mutex_cond_lock -#define __pthread_mutex_lock_full __pthread_mutex_cond_lock_full -#define NO_INCR - -#include diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_once.c b/nptl/sysdeps/unix/sysv/linux/pthread_once.c deleted file mode 100644 index 10c01d6023..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_once.c +++ /dev/null @@ -1,131 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek , 2003. - - 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, see - . */ - -#include "pthreadP.h" -#include -#include - - -unsigned long int __fork_generation attribute_hidden; - - -static void -clear_once_control (void *arg) -{ - pthread_once_t *once_control = (pthread_once_t *) arg; - - /* Reset to the uninitialized state here. We don't need a stronger memory - order because we do not need to make any other of our writes visible to - other threads that see this value: This function will be called if we - get interrupted (see __pthread_once), so all we need to relay to other - threads is the state being reset again. */ - *once_control = 0; - lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); -} - - -/* This is similar to a lock implementation, but we distinguish between three - states: not yet initialized (0), initialization finished (2), and - initialization in progress (__fork_generation | 1). If in the first state, - threads will try to run the initialization by moving to the second state; - the first thread to do so via a CAS on once_control runs init_routine, - other threads block. - When forking the process, some threads can be interrupted during the second - state; they won't be present in the forked child, so we need to restart - initialization in the child. To distinguish an in-progress initialization - from an interrupted initialization (in which case we need to reclaim the - lock), we look at the fork generation that's part of the second state: We - can reclaim iff it differs from the current fork generation. - XXX: This algorithm has an ABA issue on the fork generation: If an - initialization is interrupted, we then fork 2^30 times (30 bits of - once_control are used for the fork generation), and try to initialize - again, we can deadlock because we can't distinguish the in-progress and - interrupted cases anymore. */ -int -__pthread_once (once_control, init_routine) - pthread_once_t *once_control; - void (*init_routine) (void); -{ - while (1) - { - int oldval, val, newval; - - /* We need acquire memory order for this load because if the value - signals that initialization has finished, we need to be see any - data modifications done during initialization. */ - val = *once_control; - atomic_read_barrier(); - do - { - /* Check if the initialization has already been done. */ - if (__glibc_likely ((val & 2) != 0)) - return 0; - - oldval = val; - /* We try to set the state to in-progress and having the current - fork generation. We don't need atomic accesses for the fork - generation because it's immutable in a particular process, and - forked child processes start with a single thread that modified - the generation. */ - newval = __fork_generation | 1; - /* We need acquire memory order here for the same reason as for the - load from once_control above. */ - val = atomic_compare_and_exchange_val_acq (once_control, newval, - oldval); - } - while (__glibc_unlikely (val != oldval)); - - /* Check if another thread already runs the initializer. */ - if ((oldval & 1) != 0) - { - /* Check whether the initializer execution was interrupted by a - fork. We know that for both values, bit 0 is set and bit 1 is - not. */ - if (oldval == newval) - { - /* Same generation, some other thread was faster. Wait. */ - lll_futex_wait (once_control, newval, LLL_PRIVATE); - continue; - } - } - - /* This thread is the first here. Do the initialization. - Register a cleanup handler so that in case the thread gets - interrupted the initialization can be restarted. */ - pthread_cleanup_push (clear_once_control, once_control); - - init_routine (); - - pthread_cleanup_pop (0); - - - /* Mark *once_control as having finished the initialization. We need - release memory order here because we need to synchronize with other - threads that want to use the initialized data. */ - atomic_write_barrier(); - *once_control = 2; - - /* Wake up all other threads. */ - lll_futex_wake (once_control, INT_MAX, LLL_PRIVATE); - break; - } - - return 0; -} -weak_alias (__pthread_once, pthread_once) -hidden_def (__pthread_once) diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c b/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c deleted file mode 100644 index 874cf4b578..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_setaffinity.c +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include - - -size_t __kernel_cpumask_size attribute_hidden; - - -/* Determine the current affinity. As a side affect we learn - about the size of the cpumask_t in the kernel. */ -int -__determine_cpumask_size (pid_t tid) -{ - INTERNAL_SYSCALL_DECL (err); - int res; - - size_t psize = 128; - void *p = alloca (psize); - - while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, tid, psize, p), - INTERNAL_SYSCALL_ERROR_P (res, err) - && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) - p = extend_alloca (p, psize, 2 * psize); - - if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err)) - return INTERNAL_SYSCALL_ERRNO (res, err); - - __kernel_cpumask_size = res; - - return 0; -} - - -int -__pthread_setaffinity_new (pthread_t th, size_t cpusetsize, - const cpu_set_t *cpuset) -{ - const struct pthread *pd = (const struct pthread *) th; - - INTERNAL_SYSCALL_DECL (err); - int res; - - if (__glibc_unlikely (__kernel_cpumask_size == 0)) - { - res = __determine_cpumask_size (pd->tid); - if (res != 0) - return res; - } - - /* We now know the size of the kernel cpumask_t. Make sure the user - does not request to set a bit beyond that. */ - for (size_t cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) - if (((char *) cpuset)[cnt] != '\0') - /* Found a nonzero byte. This means the user request cannot be - fulfilled. */ - return EINVAL; - - res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, cpusetsize, - cpuset); - -#ifdef RESET_VGETCPU_CACHE - if (!INTERNAL_SYSCALL_ERROR_P (res, err)) - RESET_VGETCPU_CACHE (); -#endif - - return (INTERNAL_SYSCALL_ERROR_P (res, err) - ? INTERNAL_SYSCALL_ERRNO (res, err) - : 0); -} -versioned_symbol (libpthread, __pthread_setaffinity_new, - pthread_setaffinity_np, GLIBC_2_3_4); - - -#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) -int -__pthread_setaffinity_old (pthread_t th, cpu_set_t *cpuset) -{ - /* The old interface by default assumed a 1024 processor bitmap. */ - return __pthread_setaffinity_new (th, 128, cpuset); -} -compat_symbol (libpthread, __pthread_setaffinity_old, pthread_setaffinity_np, - GLIBC_2_3_3); -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_setname.c b/nptl/sysdeps/unix/sysv/linux/pthread_setname.c deleted file mode 100644 index 409560e586..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_setname.c +++ /dev/null @@ -1,65 +0,0 @@ -/* pthread_setname_np -- Set thread name. Linux version - Copyright (C) 2010-2014 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, see . */ - -#include -#include -#include -#include -#include -#include -#include - -#include - - -int -pthread_setname_np (th, name) - pthread_t th; - const char *name; -{ - const struct pthread *pd = (const struct pthread *) th; - - /* Unfortunately the kernel headers do not export the TASK_COMM_LEN - macro. So we have to define it here. */ -#define TASK_COMM_LEN 16 - size_t name_len = strlen (name); - if (name_len >= TASK_COMM_LEN) - return ERANGE; - - if (pd == THREAD_SELF) - return prctl (PR_SET_NAME, name) ? errno : 0; - -#define FMT "/proc/self/task/%u/comm" - char fname[sizeof (FMT) + 8]; - sprintf (fname, FMT, (unsigned int) pd->tid); - - int fd = open_not_cancel_2 (fname, O_RDWR); - if (fd == -1) - return errno; - - int res = 0; - ssize_t n = TEMP_FAILURE_RETRY (write_not_cancel (fd, name, name_len)); - if (n < 0) - res = errno; - else if (n != name_len) - res = EIO; - - close_not_cancel_no_status (fd); - - return res; -} diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c b/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c deleted file mode 100644 index 1e66815416..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_sigqueue.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (C) 2009-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2009. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include -#include - - -int -pthread_sigqueue (threadid, signo, value) - pthread_t threadid; - int signo; - const union sigval value; -{ -#ifdef __NR_rt_tgsigqueueinfo - struct pthread *pd = (struct pthread *) threadid; - - /* Make sure the descriptor is valid. */ - if (DEBUGGING_P && INVALID_TD_P (pd)) - /* Not a valid thread handle. */ - return ESRCH; - - /* Force load of pd->tid into local variable or register. Otherwise - if a thread exits between ESRCH test and tgkill, we might return - EINVAL, because pd->tid would be cleared by the kernel. */ - pid_t tid = atomic_forced_read (pd->tid); - if (__glibc_unlikely (tid <= 0)) - /* Not a valid thread handle. */ - return ESRCH; - - /* Disallow sending the signal we use for cancellation, timers, - for the setxid implementation. */ - if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) - return EINVAL; - - /* Set up the siginfo_t structure. */ - siginfo_t info; - memset (&info, '\0', sizeof (siginfo_t)); - info.si_signo = signo; - info.si_code = SI_QUEUE; - info.si_pid = THREAD_GETMEM (THREAD_SELF, pid); - info.si_uid = getuid (); - info.si_value = value; - - /* We have a special syscall to do the work. */ - INTERNAL_SYSCALL_DECL (err); - - /* One comment: The PID field in the TCB can temporarily be changed - (in fork). But this must not affect this code here. Since this - function would have to be called while the thread is executing - fork, it would have to happen in a signal handler. But this is - no allowed, pthread_sigqueue is not guaranteed to be async-safe. */ - int val = INTERNAL_SYSCALL (rt_tgsigqueueinfo, err, 4, - THREAD_GETMEM (THREAD_SELF, pid), - tid, signo, &info); - - return (INTERNAL_SYSCALL_ERROR_P (val, err) - ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); -#else - return ENOSYS; -#endif -} diff --git a/nptl/sysdeps/unix/sysv/linux/pthread_yield.c b/nptl/sysdeps/unix/sysv/linux/pthread_yield.c deleted file mode 100644 index 7f5f2065d3..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/pthread_yield.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include -#include - - -/* With the 1-on-1 model we implement this function is equivalent to - the 'sched_yield' function. */ -int -pthread_yield (void) -{ - return sched_yield (); -} diff --git a/nptl/sysdeps/unix/sysv/linux/raise.c b/nptl/sysdeps/unix/sysv/linux/raise.c deleted file mode 100644 index 4106e8c458..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/raise.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include -#include -#include -#include -#include - - -int -raise (sig) - int sig; -{ - struct pthread *pd = THREAD_SELF; - pid_t pid = THREAD_GETMEM (pd, pid); - pid_t selftid = THREAD_GETMEM (pd, tid); - if (selftid == 0) - { - /* This system call is not supposed to fail. */ -#ifdef INTERNAL_SYSCALL - INTERNAL_SYSCALL_DECL (err); - selftid = INTERNAL_SYSCALL (gettid, err, 0); -#else - selftid = INLINE_SYSCALL (gettid, 0); -#endif - THREAD_SETMEM (pd, tid, selftid); - - /* We do not set the PID field in the TID here since we might be - called from a signal handler while the thread executes fork. */ - pid = selftid; - } - else - /* raise is an async-safe function. It could be called while the - fork/vfork function temporarily invalidated the PID field. Adjust for - that. */ - if (__glibc_unlikely (pid <= 0)) - pid = (pid & INT_MAX) == 0 ? selftid : -pid; - - return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); -} -libc_hidden_def (raise) -weak_alias (raise, gsignal) diff --git a/nptl/sysdeps/unix/sysv/linux/register-atfork.c b/nptl/sysdeps/unix/sysv/linux/register-atfork.c deleted file mode 100644 index 2cc49540b9..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/register-atfork.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include -#include -#include -#include -#include - - -/* Lock to protect allocation and deallocation of fork handlers. */ -int __fork_lock = LLL_LOCK_INITIALIZER; - - -/* Number of pre-allocated handler entries. */ -#define NHANDLER 48 - -/* Memory pool for fork handler structures. */ -static struct fork_handler_pool -{ - struct fork_handler_pool *next; - struct fork_handler mem[NHANDLER]; -} fork_handler_pool; - - -static struct fork_handler * -fork_handler_alloc (void) -{ - struct fork_handler_pool *runp = &fork_handler_pool; - struct fork_handler *result = NULL; - unsigned int i; - - do - { - /* Search for an empty entry. */ - for (i = 0; i < NHANDLER; ++i) - if (runp->mem[i].refcntr == 0) - goto found; - } - while ((runp = runp->next) != NULL); - - /* We have to allocate a new entry. */ - runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp)); - if (runp != NULL) - { - /* Enqueue the new memory pool into the list. */ - runp->next = fork_handler_pool.next; - fork_handler_pool.next = runp; - - /* We use the last entry on the page. This means when we start - searching from the front the next time we will find the first - entry unused. */ - i = NHANDLER - 1; - - found: - result = &runp->mem[i]; - result->refcntr = 1; - result->need_signal = 0; - } - - return result; -} - - -int -__register_atfork (prepare, parent, child, dso_handle) - void (*prepare) (void); - void (*parent) (void); - void (*child) (void); - void *dso_handle; -{ - /* Get the lock to not conflict with other allocations. */ - lll_lock (__fork_lock, LLL_PRIVATE); - - struct fork_handler *newp = fork_handler_alloc (); - - if (newp != NULL) - { - /* Initialize the new record. */ - newp->prepare_handler = prepare; - newp->parent_handler = parent; - newp->child_handler = child; - newp->dso_handle = dso_handle; - - __linkin_atfork (newp); - } - - /* Release the lock. */ - lll_unlock (__fork_lock, LLL_PRIVATE); - - return newp == NULL ? ENOMEM : 0; -} -libc_hidden_def (__register_atfork) - - -void -attribute_hidden -__linkin_atfork (struct fork_handler *newp) -{ - do - newp->next = __fork_handlers; - while (catomic_compare_and_exchange_bool_acq (&__fork_handlers, - newp, newp->next) != 0); -} - - -libc_freeres_fn (free_mem) -{ - /* Get the lock to not conflict with running forks. */ - lll_lock (__fork_lock, LLL_PRIVATE); - - /* No more fork handlers. */ - __fork_handlers = NULL; - - /* Free eventually allocated memory blocks for the object pool. */ - struct fork_handler_pool *runp = fork_handler_pool.next; - - memset (&fork_handler_pool, '\0', sizeof (fork_handler_pool)); - - /* Release the lock. */ - lll_unlock (__fork_lock, LLL_PRIVATE); - - /* We can free the memory after releasing the lock. */ - while (runp != NULL) - { - struct fork_handler_pool *oldp = runp; - runp = runp->next; - free (oldp); - } -} diff --git a/nptl/sysdeps/unix/sysv/linux/sem_post.c b/nptl/sysdeps/unix/sysv/linux/sem_post.c deleted file mode 100644 index 4906adf332..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sem_post.c +++ /dev/null @@ -1,80 +0,0 @@ -/* sem_post -- post to a POSIX semaphore. Generic futex-using version. - Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Jakub Jelinek , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include - -#include - -int -__new_sem_post (sem_t *sem) -{ - struct new_sem *isem = (struct new_sem *) sem; - - __typeof (isem->value) cur; - do - { - cur = isem->value; - if (isem->value == SEM_VALUE_MAX) - { - __set_errno (EOVERFLOW); - return -1; - } - } - while (atomic_compare_and_exchange_bool_rel (&isem->value, cur + 1, cur)); - - atomic_full_barrier (); - if (isem->nwaiters > 0) - { - int err = lll_futex_wake (&isem->value, 1, - isem->private ^ FUTEX_PRIVATE_FLAG); - if (__builtin_expect (err, 0) < 0) - { - __set_errno (-err); - return -1; - } - } - return 0; -} -versioned_symbol (libpthread, __new_sem_post, sem_post, GLIBC_2_1); - - -#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) -int -attribute_compat_text_section -__old_sem_post (sem_t *sem) -{ - int *futex = (int *) sem; - - (void) atomic_increment_val (futex); - /* We always have to assume it is a shared semaphore. */ - int err = lll_futex_wake (futex, 1, LLL_SHARED); - if (__builtin_expect (err, 0) < 0) - { - __set_errno (-err); - return -1; - } - return 0; -} -compat_symbol (libpthread, __old_sem_post, sem_post, GLIBC_2_0); -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c b/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c deleted file mode 100644 index 7dfe51dd8b..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sem_timedwait.c +++ /dev/null @@ -1,116 +0,0 @@ -/* sem_timedwait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include - -#include -#include - - -extern void __sem_wait_cleanup (void *arg) attribute_hidden; - -/* This is in a seperate function in order to make sure gcc - puts the call site into an exception region, and thus the - cleanups get properly run. */ -static int -__attribute__ ((noinline)) -do_futex_timed_wait (struct new_sem *isem, struct timespec *rt) -{ - int err, oldtype = __pthread_enable_asynccancel (); - - err = lll_futex_timed_wait (&isem->value, 0, rt, - isem->private ^ FUTEX_PRIVATE_FLAG); - - __pthread_disable_asynccancel (oldtype); - return err; -} - -int -sem_timedwait (sem_t *sem, const struct timespec *abstime) -{ - struct new_sem *isem = (struct new_sem *) sem; - int err; - - if (atomic_decrement_if_positive (&isem->value) > 0) - return 0; - - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) - { - __set_errno (EINVAL); - return -1; - } - - atomic_increment (&isem->nwaiters); - - pthread_cleanup_push (__sem_wait_cleanup, isem); - - while (1) - { - struct timeval tv; - struct timespec rt; - int sec, nsec; - - /* Get the current time. */ - __gettimeofday (&tv, NULL); - - /* Compute relative timeout. */ - sec = abstime->tv_sec - tv.tv_sec; - nsec = abstime->tv_nsec - tv.tv_usec * 1000; - if (nsec < 0) - { - nsec += 1000000000; - --sec; - } - - /* Already timed out? */ - if (sec < 0) - { - __set_errno (ETIMEDOUT); - err = -1; - break; - } - - /* Do wait. */ - rt.tv_sec = sec; - rt.tv_nsec = nsec; - err = do_futex_timed_wait(isem, &rt); - if (err != 0 && err != -EWOULDBLOCK) - { - __set_errno (-err); - err = -1; - break; - } - - if (atomic_decrement_if_positive (&isem->value) > 0) - { - err = 0; - break; - } - } - - pthread_cleanup_pop (0); - - atomic_decrement (&isem->nwaiters); - - return err; -} diff --git a/nptl/sysdeps/unix/sysv/linux/sem_trywait.c b/nptl/sysdeps/unix/sysv/linux/sem_trywait.c deleted file mode 100644 index 94c323c18e..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sem_trywait.c +++ /dev/null @@ -1,50 +0,0 @@ -/* sem_trywait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include -#include - -#include - - -int -__new_sem_trywait (sem_t *sem) -{ - int *futex = (int *) sem; - int val; - - if (*futex > 0) - { - val = atomic_decrement_if_positive (futex); - if (val > 0) - return 0; - } - - __set_errno (EAGAIN); - return -1; -} -versioned_symbol (libpthread, __new_sem_trywait, sem_trywait, GLIBC_2_1); -#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) -strong_alias (__new_sem_trywait, __old_sem_trywait) -compat_symbol (libpthread, __old_sem_trywait, sem_trywait, GLIBC_2_0); -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sem_wait.c b/nptl/sysdeps/unix/sysv/linux/sem_wait.c deleted file mode 100644 index b12babb596..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sem_wait.c +++ /dev/null @@ -1,123 +0,0 @@ -/* sem_wait -- wait on a semaphore. Generic futex-using version. - Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Paul Mackerras , 2003. - - 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, see - . */ - -#include -#include -#include -#include -#include - -#include -#include -#include - - -void -attribute_hidden -__sem_wait_cleanup (void *arg) -{ - struct new_sem *isem = (struct new_sem *) arg; - - atomic_decrement (&isem->nwaiters); -} - -/* This is in a seperate function in order to make sure gcc - puts the call site into an exception region, and thus the - cleanups get properly run. */ -static int -__attribute__ ((noinline)) -do_futex_wait (struct new_sem *isem) -{ - int err, oldtype = __pthread_enable_asynccancel (); - - err = lll_futex_wait (&isem->value, 0, isem->private ^ FUTEX_PRIVATE_FLAG); - - __pthread_disable_asynccancel (oldtype); - return err; -} - -int -__new_sem_wait (sem_t *sem) -{ - struct new_sem *isem = (struct new_sem *) sem; - int err; - - if (atomic_decrement_if_positive (&isem->value) > 0) - return 0; - - atomic_increment (&isem->nwaiters); - - pthread_cleanup_push (__sem_wait_cleanup, isem); - - while (1) - { - err = do_futex_wait(isem); - if (err != 0 && err != -EWOULDBLOCK) - { - __set_errno (-err); - err = -1; - break; - } - - if (atomic_decrement_if_positive (&isem->value) > 0) - { - err = 0; - break; - } - } - - pthread_cleanup_pop (0); - - atomic_decrement (&isem->nwaiters); - - return err; -} -versioned_symbol (libpthread, __new_sem_wait, sem_wait, GLIBC_2_1); - - -#if SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_1) -int -attribute_compat_text_section -__old_sem_wait (sem_t *sem) -{ - int *futex = (int *) sem; - int err; - - do - { - if (atomic_decrement_if_positive (futex) > 0) - return 0; - - /* Enable asynchronous cancellation. Required by the standard. */ - int oldtype = __pthread_enable_asynccancel (); - - /* Always assume the semaphore is shared. */ - err = lll_futex_wait (futex, 0, LLL_SHARED); - - /* Disable asynchronous cancellation. */ - __pthread_disable_asynccancel (oldtype); - } - while (err == 0 || err == -EWOULDBLOCK); - - __set_errno (-err); - return -1; -} - -compat_symbol (libpthread, __old_sem_wait, sem_wait, GLIBC_2_0); -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c b/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c deleted file mode 100644 index 8560e8b40a..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sigtimedwait.c +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include "../../../../../sysdeps/unix/sysv/linux/sigtimedwait.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sigwait.c b/nptl/sysdeps/unix/sysv/linux/sigwait.c deleted file mode 100644 index c358bfbeed..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sigwait.c +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include "../../../../../sysdeps/unix/sysv/linux/sigwait.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c b/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c deleted file mode 100644 index a4f9fe8f5f..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sigwaitinfo.c +++ /dev/null @@ -1,2 +0,0 @@ -#include -#include "../../../../../sysdeps/unix/sysv/linux/sigwaitinfo.c" diff --git a/nptl/sysdeps/unix/sysv/linux/sleep.c b/nptl/sysdeps/unix/sysv/linux/sleep.c deleted file mode 100644 index 2dce3210ca..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/sleep.c +++ /dev/null @@ -1,10 +0,0 @@ -/* We want an #include_next, but we are the main source file. - So, #include ourselves and in that incarnation we can use #include_next. */ -#ifndef INCLUDED_SELF -# define INCLUDED_SELF -# include -#else -/* This defines the CANCELLATION_P macro, which sleep.c checks for. */ -# include -# include_next -#endif diff --git a/nptl/sysdeps/unix/sysv/linux/structsem.sym b/nptl/sysdeps/unix/sysv/linux/structsem.sym deleted file mode 100644 index 0e2a15f2b5..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/structsem.sym +++ /dev/null @@ -1,12 +0,0 @@ -#include -#include -#include -#include -#include "internaltypes.h" - --- - -VALUE offsetof (struct new_sem, value) -PRIVATE offsetof (struct new_sem, private) -NWAITERS offsetof (struct new_sem, nwaiters) -SEM_VALUE_MAX SEM_VALUE_MAX diff --git a/nptl/sysdeps/unix/sysv/linux/timer_create.c b/nptl/sysdeps/unix/sysv/linux/timer_create.c deleted file mode 100644 index e5c056bf2c..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/timer_create.c +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see . */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "kernel-posix-timers.h" -#include "kernel-posix-cpu-timers.h" - - -#ifdef timer_create_alias -# define timer_create timer_create_alias -#endif - - -int -timer_create (clock_id, evp, timerid) - clockid_t clock_id; - struct sigevent *evp; - timer_t *timerid; -{ -#undef timer_create - { - clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID - ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED) - : clock_id == CLOCK_THREAD_CPUTIME_ID - ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED) - : clock_id); - - /* If the user wants notification via a thread we need to handle - this special. */ - if (evp == NULL - || __builtin_expect (evp->sigev_notify != SIGEV_THREAD, 1)) - { - struct sigevent local_evp; - - /* We avoid allocating too much memory by basically - using struct timer as a derived class with the - first two elements being in the superclass. We only - need these two elements here. */ - struct timer *newp = (struct timer *) malloc (offsetof (struct timer, - thrfunc)); - if (newp == NULL) - /* No more memory. */ - return -1; - - if (evp == NULL) - { - /* The kernel has to pass up the timer ID which is a - userlevel object. Therefore we cannot leave it up to - the kernel to determine it. */ - local_evp.sigev_notify = SIGEV_SIGNAL; - local_evp.sigev_signo = SIGALRM; - local_evp.sigev_value.sival_ptr = newp; - - evp = &local_evp; - } - - kernel_timer_t ktimerid; - int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp, - &ktimerid); - - if (retval != -1) - { - newp->sigev_notify = (evp != NULL - ? evp->sigev_notify : SIGEV_SIGNAL); - newp->ktimerid = ktimerid; - - *timerid = (timer_t) newp; - } - else - { - /* Cannot allocate the timer, fail. */ - free (newp); - retval = -1; - } - - return retval; - } - else - { - /* Create the helper thread. */ - pthread_once (&__helper_once, __start_helper_thread); - if (__helper_tid == 0) - { - /* No resources to start the helper thread. */ - __set_errno (EAGAIN); - return -1; - } - - struct timer *newp; - newp = (struct timer *) malloc (sizeof (struct timer)); - if (newp == NULL) - return -1; - - /* Copy the thread parameters the user provided. */ - newp->sival = evp->sigev_value; - newp->thrfunc = evp->sigev_notify_function; - newp->sigev_notify = SIGEV_THREAD; - - /* We cannot simply copy the thread attributes since the - implementation might keep internal information for - each instance. */ - (void) pthread_attr_init (&newp->attr); - if (evp->sigev_notify_attributes != NULL) - { - struct pthread_attr *nattr; - struct pthread_attr *oattr; - - nattr = (struct pthread_attr *) &newp->attr; - oattr = (struct pthread_attr *) evp->sigev_notify_attributes; - - nattr->schedparam = oattr->schedparam; - nattr->schedpolicy = oattr->schedpolicy; - nattr->flags = oattr->flags; - nattr->guardsize = oattr->guardsize; - nattr->stackaddr = oattr->stackaddr; - nattr->stacksize = oattr->stacksize; - } - - /* In any case set the detach flag. */ - (void) pthread_attr_setdetachstate (&newp->attr, - PTHREAD_CREATE_DETACHED); - - /* Create the event structure for the kernel timer. */ - struct sigevent sev = - { .sigev_value.sival_ptr = newp, - .sigev_signo = SIGTIMER, - .sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID, - ._sigev_un = { ._pad = { [0] = __helper_tid } } }; - - /* Create the timer. */ - INTERNAL_SYSCALL_DECL (err); - int res; - res = INTERNAL_SYSCALL (timer_create, err, 3, - syscall_clockid, &sev, &newp->ktimerid); - if (! INTERNAL_SYSCALL_ERROR_P (res, err)) - { - /* Add to the queue of active timers with thread - delivery. */ - pthread_mutex_lock (&__active_timer_sigev_thread_lock); - newp->next = __active_timer_sigev_thread; - __active_timer_sigev_thread = newp; - pthread_mutex_unlock (&__active_timer_sigev_thread_lock); - - *timerid = (timer_t) newp; - return 0; - } - - /* Free the resources. */ - free (newp); - - __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); - - return -1; - } - } -} diff --git a/nptl/sysdeps/unix/sysv/linux/timer_delete.c b/nptl/sysdeps/unix/sysv/linux/timer_delete.c deleted file mode 100644 index 1de81236e2..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/timer_delete.c +++ /dev/null @@ -1,73 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see . */ - -#include -#include -#include -#include -#include "kernel-posix-timers.h" - - -#ifdef timer_delete_alias -# define timer_delete timer_delete_alias -#endif - - -int -timer_delete (timerid) - timer_t timerid; -{ -#undef timer_delete - struct timer *kt = (struct timer *) timerid; - - /* Delete the kernel timer object. */ - int res = INLINE_SYSCALL (timer_delete, 1, kt->ktimerid); - - if (res == 0) - { - if (kt->sigev_notify == SIGEV_THREAD) - { - /* Remove the timer from the list. */ - pthread_mutex_lock (&__active_timer_sigev_thread_lock); - if (__active_timer_sigev_thread == kt) - __active_timer_sigev_thread = kt->next; - else - { - struct timer *prevp = __active_timer_sigev_thread; - while (prevp->next != NULL) - if (prevp->next == kt) - { - prevp->next = kt->next; - break; - } - else - prevp = prevp->next; - } - pthread_mutex_unlock (&__active_timer_sigev_thread_lock); - } - - /* Free the memory. */ - (void) free (kt); - - return 0; - } - - /* The kernel timer is not known or something else bad happened. - Return the error. */ - return -1; -} diff --git a/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c b/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c deleted file mode 100644 index 0ac394114e..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/timer_getoverr.c +++ /dev/null @@ -1,41 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see . */ - -#include -#include -#include -#include "kernel-posix-timers.h" - - -#ifdef timer_getoverrun_alias -# define timer_getoverrun timer_getoverrun_alias -#endif - - -int -timer_getoverrun (timerid) - timer_t timerid; -{ -#undef timer_getoverrun - struct timer *kt = (struct timer *) timerid; - - /* Get the information from the kernel. */ - int res = INLINE_SYSCALL (timer_getoverrun, 1, kt->ktimerid); - - return res; -} diff --git a/nptl/sysdeps/unix/sysv/linux/timer_gettime.c b/nptl/sysdeps/unix/sysv/linux/timer_gettime.c deleted file mode 100644 index 7783034a76..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/timer_gettime.c +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see . */ - -#include -#include -#include -#include -#include "kernel-posix-timers.h" - - -#ifdef timer_gettime_alias -# define timer_gettime timer_gettime_alias -#endif - - -int -timer_gettime (timerid, value) - timer_t timerid; - struct itimerspec *value; -{ -#undef timer_gettime - struct timer *kt = (struct timer *) timerid; - - /* Delete the kernel timer object. */ - int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value); - - return res; -} diff --git a/nptl/sysdeps/unix/sysv/linux/timer_routines.c b/nptl/sysdeps/unix/sysv/linux/timer_routines.c deleted file mode 100644 index 4ac9bbe896..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/timer_routines.c +++ /dev/null @@ -1,196 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see . */ - -#include -#include -#include -#include -#include -#include -#include "kernel-posix-timers.h" - - -/* List of active SIGEV_THREAD timers. */ -struct timer *__active_timer_sigev_thread; -/* Lock for the __active_timer_sigev_thread. */ -pthread_mutex_t __active_timer_sigev_thread_lock = PTHREAD_MUTEX_INITIALIZER; - - -struct thread_start_data -{ - void (*thrfunc) (sigval_t); - sigval_t sival; -}; - - -/* Helper thread to call the user-provided function. */ -static void * -timer_sigev_thread (void *arg) -{ - /* The parent thread has all signals blocked. This is a bit - surprising for user code, although valid. We unblock all - signals. */ - sigset_t ss; - sigemptyset (&ss); - INTERNAL_SYSCALL_DECL (err); - INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); - - struct thread_start_data *td = (struct thread_start_data *) arg; - - void (*thrfunc) (sigval_t) = td->thrfunc; - sigval_t sival = td->sival; - - /* The TD object was allocated in timer_helper_thread. */ - free (td); - - /* Call the user-provided function. */ - thrfunc (sival); - - return NULL; -} - - -/* Helper function to support starting threads for SIGEV_THREAD. */ -static void * -timer_helper_thread (void *arg) -{ - /* Wait for the SIGTIMER signal, allowing the setXid signal, and - none else. */ - sigset_t ss; - sigemptyset (&ss); - __sigaddset (&ss, SIGTIMER); - - /* Endless loop of waiting for signals. The loop is only ended when - the thread is canceled. */ - while (1) - { - siginfo_t si; - - /* sigwaitinfo cannot be used here, since it deletes - SIGCANCEL == SIGTIMER from the set. */ - - int oldtype = LIBC_CANCEL_ASYNC (); - - /* XXX The size argument hopefully will have to be changed to the - real size of the user-level sigset_t. */ - int result = INLINE_SYSCALL (rt_sigtimedwait, 4, &ss, &si, NULL, - _NSIG / 8); - - LIBC_CANCEL_RESET (oldtype); - - if (result > 0) - { - if (si.si_code == SI_TIMER) - { - struct timer *tk = (struct timer *) si.si_ptr; - - /* Check the timer is still used and will not go away - while we are reading the values here. */ - pthread_mutex_lock (&__active_timer_sigev_thread_lock); - - struct timer *runp = __active_timer_sigev_thread; - while (runp != NULL) - if (runp == tk) - break; - else - runp = runp->next; - - if (runp != NULL) - { - struct thread_start_data *td = malloc (sizeof (*td)); - - /* There is not much we can do if the allocation fails. */ - if (td != NULL) - { - /* This is the signal we are waiting for. */ - td->thrfunc = tk->thrfunc; - td->sival = tk->sival; - - pthread_t th; - (void) pthread_create (&th, &tk->attr, - timer_sigev_thread, td); - } - } - - pthread_mutex_unlock (&__active_timer_sigev_thread_lock); - } - else if (si.si_code == SI_TKILL) - /* The thread is canceled. */ - pthread_exit (NULL); - } - } -} - - -/* Control variable for helper thread creation. */ -pthread_once_t __helper_once attribute_hidden; - - -/* TID of the helper thread. */ -pid_t __helper_tid attribute_hidden; - - -/* Reset variables so that after a fork a new helper thread gets started. */ -static void -reset_helper_control (void) -{ - __helper_once = PTHREAD_ONCE_INIT; - __helper_tid = 0; -} - - -void -attribute_hidden -__start_helper_thread (void) -{ - /* The helper thread needs only very little resources - and should go away automatically when canceled. */ - pthread_attr_t attr; - (void) pthread_attr_init (&attr); - (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); - - /* Block all signals in the helper thread but SIGSETXID. To do this - thoroughly we temporarily have to block all signals here. The - helper can lose wakeups if SIGCANCEL is not blocked throughout, - but sigfillset omits it SIGSETXID. So, we add SIGCANCEL back - explicitly here. */ - sigset_t ss; - sigset_t oss; - sigfillset (&ss); - __sigaddset (&ss, SIGCANCEL); - INTERNAL_SYSCALL_DECL (err); - INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); - - /* Create the helper thread for this timer. */ - pthread_t th; - int res = pthread_create (&th, &attr, timer_helper_thread, NULL); - if (res == 0) - /* We managed to start the helper thread. */ - __helper_tid = ((struct pthread *) th)->tid; - - /* Restore the signal mask. */ - INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, - _NSIG / 8); - - /* No need for the attribute anymore. */ - (void) pthread_attr_destroy (&attr); - - /* We have to make sure that after fork()ing a new helper thread can - be created. */ - pthread_atfork (NULL, NULL, reset_helper_control); -} diff --git a/nptl/sysdeps/unix/sysv/linux/timer_settime.c b/nptl/sysdeps/unix/sysv/linux/timer_settime.c deleted file mode 100644 index f7f7c91c51..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/timer_settime.c +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2003-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 2003. - - 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, see . */ - -#include -#include -#include -#include -#include "kernel-posix-timers.h" - - -#ifdef timer_settime_alias -# define timer_settime timer_settime_alias -#endif - - -int -timer_settime (timerid, flags, value, ovalue) - timer_t timerid; - int flags; - const struct itimerspec *value; - struct itimerspec *ovalue; -{ -#undef timer_settime - struct timer *kt = (struct timer *) timerid; - - /* Delete the kernel timer object. */ - int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags, - value, ovalue); - - return res; -} diff --git a/nptl/sysdeps/unix/sysv/linux/tst-setgetname.c b/nptl/sysdeps/unix/sysv/linux/tst-setgetname.c deleted file mode 100644 index f5693e26c4..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/tst-setgetname.c +++ /dev/null @@ -1,315 +0,0 @@ -/* Test pthread_setname_np and pthread_getname_np. - Copyright (C) 2013-2014 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, see . */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* New name of process. */ -#define NEW_NAME "setname" - -/* Name of process which is one byte too big - e.g. 17 bytes including null-terminator */ -#define BIG_NAME "....V....X....XV" - -/* Longest name of a process - e.g. 16 bytes including null-terminator. */ -#define LONGEST_NAME "....V....X....X" - -/* One less than longest name with unique - characters to detect modification. */ -#define CANARY_NAME "abcdefghijklmn" - -/* On Linux the maximum length of the name of a task *including* the null - terminator. */ -#define TASK_COMM_LEN 16 - -long -gettid (void) -{ - return syscall(__NR_gettid); -} - -/* On Linux we can read this task's name from /proc. */ -int -get_self_comm (long tid, char *buf, size_t len) -{ - int res = 0; -#define FMT "/proc/self/task/%lu/comm" - char fname[sizeof (FMT) + 8]; - sprintf (fname, FMT, (unsigned long) tid); - - int fd = open (fname, O_RDONLY); - if (fd == -1) - return errno; - - ssize_t n = read (fd, (void *) buf, len); - if (n < 0) - res = errno; - else - { - if (buf[n - 1] == '\n') - buf[n - 1] = '\0'; - else if (n == len) - res = ERANGE; - else - buf[n] = '\0'; - } - - close (fd); - return res; -} - -int -do_test (int argc, char **argv) -{ - pthread_t self; - int res; - int ret = 0; - char name[TASK_COMM_LEN]; - char name_check[TASK_COMM_LEN]; - - memset (name, '\0', TASK_COMM_LEN); - memset (name_check, '\0', TASK_COMM_LEN); - - /* Test 1: Get the name of the task via pthread_getname_np and /proc - and verify that they both match. */ - self = pthread_self (); - res = pthread_getname_np (self, name, TASK_COMM_LEN); - - if (res == 0) - { - res = get_self_comm (gettid (), name_check, TASK_COMM_LEN); - -#if !__ASSUME_PROC_PID_TASK_COMM - /* On this first test we look for ENOENT to be returned from - get_self_comm to indicate that the kernel is older than - 2.6.33 and doesn't contain comm within the proc structure. - In that case we skip the entire test. */ - if (res == ENOENT) - { - printf ("SKIP: The kernel does not have /proc/self/task/%%lu/comm.\n"); - return 0; - } -#endif - - if (res == 0) - { - if (strncmp (name, name_check, strlen (BIG_NAME)) == 0) - printf ("PASS: Test 1 - pthread_getname_np and /proc agree.\n"); - else - { - printf ("FAIL: Test 1 - pthread_getname_np and /proc differ" - " i.e. %s != %s\n", name, name_check); - ret++; - } - } - else - { - printf ("FAIL: Test 1 - unable read task name via proc.\n"); - ret++; - } - } - else - { - printf ("FAIL: Test 1 - pthread_getname_np failed with error %d\n", res); - ret++; - } - - /* Test 2: Test setting the name and then independently verify it - was set. */ - res = pthread_setname_np (self, NEW_NAME); - - if (res == 0) - { - res = get_self_comm (gettid (), name_check, TASK_COMM_LEN); - if (res == 0) - { - if (strncmp (NEW_NAME, name_check, strlen (BIG_NAME)) == 0) - printf ("PASS: Test 2 - Value used in pthread_setname_np and" - " /proc agree.\n"); - else - { - printf ("FAIL: Test 2 - Value used in pthread_setname_np" - " and /proc differ i.e. %s != %s\n", - NEW_NAME, name_check); - ret++; - } - } - else - { - printf ("FAIL: Test 2 - unable to read task name via proc.\n"); - ret++; - } - } - else - { - printf ("FAIL: Test 2 - pthread_setname_np failed with error %d\n", res); - ret++; - } - - /* Test 3: Test setting a name that is one-byte too big. */ - res = pthread_getname_np (self, name, TASK_COMM_LEN); - - if (res == 0) - { - res = pthread_setname_np (self, BIG_NAME); - if (res != 0) - { - if (res == ERANGE) - { - printf ("PASS: Test 3 - pthread_setname_np returned ERANGE" - " for a process name that was too long.\n"); - - /* Verify the old name didn't change. */ - res = get_self_comm (gettid (), name_check, TASK_COMM_LEN); - if (res == 0) - { - if (strncmp (name, name_check, strlen (BIG_NAME)) == 0) - printf ("PASS: Test 3 - Original name unchanged after" - " pthread_setname_np returned ERANGE.\n"); - else - { - printf ("FAIL: Test 3 - Original name changed after" - " pthread_setname_np returned ERANGE" - " i.e. %s != %s\n", - name, name_check); - ret++; - } - } - else - { - printf ("FAIL: Test 3 - unable to read task name.\n"); - ret++; - } - } - else - { - printf ("FAIL: Test 3 - Wrong error returned" - " i.e. ERANGE != %d\n", res); - ret++; - } - } - else - { - printf ("FAIL: Test 3 - Too-long name accepted by" - " pthread_setname_np.\n"); - ret++; - } - } - else - { - printf ("FAIL: Test 3 - Unable to get original name.\n"); - ret++; - } - - /* Test 4: Verify that setting the longest name works. */ - res = pthread_setname_np (self, LONGEST_NAME); - - if (res == 0) - { - res = get_self_comm (gettid (), name_check, TASK_COMM_LEN); - if (res == 0) - { - if (strncmp (LONGEST_NAME, name_check, strlen (BIG_NAME)) == 0) - printf ("PASS: Test 4 - Longest name set via pthread_setname_np" - " agrees with /proc.\n"); - else - { - printf ("FAIL: Test 4 - Value used in pthread_setname_np and /proc" - " differ i.e. %s != %s\n", LONGEST_NAME, name_check); - ret++; - } - } - else - { - printf ("FAIL: Test 4 - unable to read task name via proc.\n"); - ret++; - } - } - else - { - printf ("FAIL: Test 4 - pthread_setname_np failed with error %d\n", res); - ret++; - } - - /* Test 5: Verify that getting a long name into a small buffer fails. */ - strncpy (name, CANARY_NAME, strlen (CANARY_NAME) + 1); - - /* Claim the buffer length is strlen (LONGEST_NAME). This is one character - too small to hold LONGEST_NAME *and* the null terminator. We should get - back ERANGE and name should be unmodified. */ - res = pthread_getname_np (self, name, strlen (LONGEST_NAME)); - - if (res != 0) - { - if (res == ERANGE) - { - if (strncmp (CANARY_NAME, name, strlen (BIG_NAME)) == 0) - { - printf ("PASS: Test 5 - ERANGE and buffer unmodified.\n"); - } - else - { - printf ("FAIL: Test 5 - Original buffer modified.\n"); - ret++; - } - } - else - { - printf ("FAIL: Test 5 - Did not return ERANGE for small buffer.\n"); - ret++; - } - } - else - { - printf ("FAIL: Test 5 - Returned name longer than buffer.\n"); - ret++; - } - - /* Test 6: Lastly make sure we can read back the longest name. */ - res = pthread_getname_np (self, name, strlen (LONGEST_NAME) + 1); - - if (res == 0) - { - if (strncmp (LONGEST_NAME, name, strlen (BIG_NAME)) == 0) - { - printf ("PASS: Test 6 - Read back longest name correctly.\n"); - } - else - { - printf ("FAIL: Test 6 - Read \"%s\" instead of longest name.\n", - name); - ret++; - } - } - else - { - printf ("FAIL: Test 6 - pthread_getname_np failed with error %d\n", res); - ret++; - } - - return ret; -} - -#include diff --git a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c b/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c deleted file mode 100644 index 9005160f99..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/unregister-atfork.c +++ /dev/null @@ -1,121 +0,0 @@ -/* Copyright (C) 2002-2014 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Ulrich Drepper , 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, see - . */ - -#include -#include -#include -#include - - -void -__unregister_atfork (dso_handle) - void *dso_handle; -{ - /* Check whether there is any entry in the list which we have to - remove. It is likely that this is not the case so don't bother - getting the lock. - - We do not worry about other threads adding entries for this DSO - right this moment. If this happens this is a race and we can do - whatever we please. The program will crash anyway seen. */ - struct fork_handler *runp = __fork_handlers; - struct fork_handler *lastp = NULL; - - while (runp != NULL) - if (runp->dso_handle == dso_handle) - break; - else - { - lastp = runp; - runp = runp->next; - } - - if (runp == NULL) - /* Nothing to do. */ - return; - - /* Get the lock to not conflict with additions or deletions. Note - that there couldn't have been another thread deleting something. - The __unregister_atfork function is only called from the - dlclose() code which itself serializes the operations. */ - lll_lock (__fork_lock, LLL_PRIVATE); - - /* We have to create a new list with all the entries we don't remove. */ - struct deleted_handler - { - struct fork_handler *handler; - struct deleted_handler *next; - } *deleted = NULL; - - /* Remove the entries for the DSO which is unloaded from the list. - It's a single linked list so readers are. */ - do - { - again: - if (runp->dso_handle == dso_handle) - { - if (lastp == NULL) - { - /* We have to use an atomic operation here because - __linkin_atfork also uses one. */ - if (catomic_compare_and_exchange_bool_acq (&__fork_handlers, - runp->next, runp) - != 0) - { - runp = __fork_handlers; - goto again; - } - } - else - lastp->next = runp->next; - - /* We cannot overwrite the ->next element now. Put the deleted - entries in a separate list. */ - struct deleted_handler *newp = alloca (sizeof (*newp)); - newp->handler = runp; - newp->next = deleted; - deleted = newp; - } - else - lastp = runp; - - runp = runp->next; - } - while (runp != NULL); - - /* Release the lock. */ - lll_unlock (__fork_lock, LLL_PRIVATE); - - /* Walk the list of all entries which have to be deleted. */ - while (deleted != NULL) - { - /* We need to be informed by possible current users. */ - deleted->handler->need_signal = 1; - /* Make sure this gets written out first. */ - atomic_write_barrier (); - - /* Decrement the reference counter. If it does not reach zero - wait for the last user. */ - atomic_decrement (&deleted->handler->refcntr); - unsigned int val; - while ((val = deleted->handler->refcntr) != 0) - lll_futex_wait (&deleted->handler->refcntr, val, LLL_PRIVATE); - - deleted = deleted->next; - } -} diff --git a/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym b/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym deleted file mode 100644 index 8044b4078c..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/unwindbuf.sym +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include - --- - -UNWINDBUFSIZE sizeof (__pthread_unwind_buf_t) -UWJMPBUF offsetof (__pthread_unwind_buf_t, __cancel_jmp_buf) diff --git a/nptl/unregister-atfork.c b/nptl/unregister-atfork.c new file mode 100644 index 0000000000..9005160f99 --- /dev/null +++ b/nptl/unregister-atfork.c @@ -0,0 +1,121 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include +#include +#include +#include + + +void +__unregister_atfork (dso_handle) + void *dso_handle; +{ + /* Check whether there is any entry in the list which we have to + remove. It is likely that this is not the case so don't bother + getting the lock. + + We do not worry about other threads adding entries for this DSO + right this moment. If this happens this is a race and we can do + whatever we please. The program will crash anyway seen. */ + struct fork_handler *runp = __fork_handlers; + struct fork_handler *lastp = NULL; + + while (runp != NULL) + if (runp->dso_handle == dso_handle) + break; + else + { + lastp = runp; + runp = runp->next; + } + + if (runp == NULL) + /* Nothing to do. */ + return; + + /* Get the lock to not conflict with additions or deletions. Note + that there couldn't have been another thread deleting something. + The __unregister_atfork function is only called from the + dlclose() code which itself serializes the operations. */ + lll_lock (__fork_lock, LLL_PRIVATE); + + /* We have to create a new list with all the entries we don't remove. */ + struct deleted_handler + { + struct fork_handler *handler; + struct deleted_handler *next; + } *deleted = NULL; + + /* Remove the entries for the DSO which is unloaded from the list. + It's a single linked list so readers are. */ + do + { + again: + if (runp->dso_handle == dso_handle) + { + if (lastp == NULL) + { + /* We have to use an atomic operation here because + __linkin_atfork also uses one. */ + if (catomic_compare_and_exchange_bool_acq (&__fork_handlers, + runp->next, runp) + != 0) + { + runp = __fork_handlers; + goto again; + } + } + else + lastp->next = runp->next; + + /* We cannot overwrite the ->next element now. Put the deleted + entries in a separate list. */ + struct deleted_handler *newp = alloca (sizeof (*newp)); + newp->handler = runp; + newp->next = deleted; + deleted = newp; + } + else + lastp = runp; + + runp = runp->next; + } + while (runp != NULL); + + /* Release the lock. */ + lll_unlock (__fork_lock, LLL_PRIVATE); + + /* Walk the list of all entries which have to be deleted. */ + while (deleted != NULL) + { + /* We need to be informed by possible current users. */ + deleted->handler->need_signal = 1; + /* Make sure this gets written out first. */ + atomic_write_barrier (); + + /* Decrement the reference counter. If it does not reach zero + wait for the last user. */ + atomic_decrement (&deleted->handler->refcntr); + unsigned int val; + while ((val = deleted->handler->refcntr) != 0) + lll_futex_wait (&deleted->handler->refcntr, val, LLL_PRIVATE); + + deleted = deleted->next; + } +} diff --git a/nptl/unwindbuf.sym b/nptl/unwindbuf.sym new file mode 100644 index 0000000000..8044b4078c --- /dev/null +++ b/nptl/unwindbuf.sym @@ -0,0 +1,7 @@ +#include +#include + +-- + +UNWINDBUFSIZE sizeof (__pthread_unwind_buf_t) +UWJMPBUF offsetof (__pthread_unwind_buf_t, __cancel_jmp_buf) diff --git a/sysdeps/nptl/fork.c b/sysdeps/nptl/fork.c new file mode 100644 index 0000000000..70201a294c --- /dev/null +++ b/sysdeps/nptl/fork.c @@ -0,0 +1,238 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +unsigned long int *__fork_generation_pointer; + + + +/* The single linked list of all currently registered fork handlers. */ +struct fork_handler *__fork_handlers; + + +static void +fresetlockfiles (void) +{ + _IO_ITER i; + + for (i = _IO_iter_begin(); i != _IO_iter_end(); i = _IO_iter_next(i)) + _IO_lock_init (*((_IO_lock_t *) _IO_iter_file(i)->_lock)); +} + + +pid_t +__libc_fork (void) +{ + pid_t pid; + struct used_handler + { + struct fork_handler *handler; + struct used_handler *next; + } *allp = NULL; + + /* Run all the registered preparation handlers. In reverse order. + While doing this we build up a list of all the entries. */ + struct fork_handler *runp; + while ((runp = __fork_handlers) != NULL) + { + /* Make sure we read from the current RUNP pointer. */ + atomic_full_barrier (); + + unsigned int oldval = runp->refcntr; + + if (oldval == 0) + /* This means some other thread removed the list just after + the pointer has been loaded. Try again. Either the list + is empty or we can retry it. */ + continue; + + /* Bump the reference counter. */ + if (atomic_compare_and_exchange_bool_acq (&__fork_handlers->refcntr, + oldval + 1, oldval)) + /* The value changed, try again. */ + continue; + + /* We bumped the reference counter for the first entry in the + list. That means that none of the following entries will + just go away. The unloading code works in the order of the + list. + + While executing the registered handlers we are building a + list of all the entries so that we can go backward later on. */ + while (1) + { + /* Execute the handler if there is one. */ + if (runp->prepare_handler != NULL) + runp->prepare_handler (); + + /* Create a new element for the list. */ + struct used_handler *newp + = (struct used_handler *) alloca (sizeof (*newp)); + newp->handler = runp; + newp->next = allp; + allp = newp; + + /* Advance to the next handler. */ + runp = runp->next; + if (runp == NULL) + break; + + /* Bump the reference counter for the next entry. */ + atomic_increment (&runp->refcntr); + } + + /* We are done. */ + break; + } + + _IO_list_lock (); + +#ifndef NDEBUG + pid_t ppid = THREAD_GETMEM (THREAD_SELF, tid); +#endif + + /* We need to prevent the getpid() code to update the PID field so + that, if a signal arrives in the child very early and the signal + handler uses getpid(), the value returned is correct. */ + pid_t parentpid = THREAD_GETMEM (THREAD_SELF, pid); + THREAD_SETMEM (THREAD_SELF, pid, -parentpid); + +#ifdef ARCH_FORK + pid = ARCH_FORK (); +#else +# error "ARCH_FORK must be defined so that the CLONE_SETTID flag is used" + pid = INLINE_SYSCALL (fork, 0); +#endif + + + if (pid == 0) + { + struct pthread *self = THREAD_SELF; + + assert (THREAD_GETMEM (self, tid) != ppid); + + if (__fork_generation_pointer != NULL) + *__fork_generation_pointer += 4; + + /* Adjust the PID field for the new process. */ + THREAD_SETMEM (self, pid, THREAD_GETMEM (self, tid)); + +#if HP_TIMING_AVAIL + /* The CPU clock of the thread and process have to be set to zero. */ + hp_timing_t now; + HP_TIMING_NOW (now); + THREAD_SETMEM (self, cpuclock_offset, now); + GL(dl_cpuclock_offset) = now; +#endif + +#ifdef __NR_set_robust_list + /* Initialize the robust mutex list which has been reset during + the fork. We do not check for errors since if it fails here + it failed at process start as well and noone could have used + robust mutexes. We also do not have to set + self->robust_head.futex_offset since we inherit the correct + value from the parent. */ +# ifdef SHARED + if (__builtin_expect (__libc_pthread_functions_init, 0)) + PTHFCT_CALL (ptr_set_robust, (self)); +# else + extern __typeof (__nptl_set_robust) __nptl_set_robust + __attribute__((weak)); + if (__builtin_expect (__nptl_set_robust != NULL, 0)) + __nptl_set_robust (self); +# endif +#endif + + /* Reset the file list. These are recursive mutexes. */ + fresetlockfiles (); + + /* Reset locks in the I/O code. */ + _IO_list_resetlock (); + + /* Reset the lock the dynamic loader uses to protect its data. */ + __rtld_lock_initialize (GL(dl_load_lock)); + + /* Run the handlers registered for the child. */ + while (allp != NULL) + { + if (allp->handler->child_handler != NULL) + allp->handler->child_handler (); + + /* Note that we do not have to wake any possible waiter. + This is the only thread in the new process. The count + may have been bumped up by other threads doing a fork. + We reset it to 1, to avoid waiting for non-existing + thread(s) to release the count. */ + allp->handler->refcntr = 1; + + /* XXX We could at this point look through the object pool + and mark all objects not on the __fork_handlers list as + unused. This is necessary in case the fork() happened + while another thread called dlclose() and that call had + to create a new list. */ + + allp = allp->next; + } + + /* Initialize the fork lock. */ + __fork_lock = LLL_LOCK_INITIALIZER; + } + else + { + assert (THREAD_GETMEM (THREAD_SELF, tid) == ppid); + + /* Restore the PID value. */ + THREAD_SETMEM (THREAD_SELF, pid, parentpid); + + /* We execute this even if the 'fork' call failed. */ + _IO_list_unlock (); + + /* Run the handlers registered for the parent. */ + while (allp != NULL) + { + if (allp->handler->parent_handler != NULL) + allp->handler->parent_handler (); + + if (atomic_decrement_and_test (&allp->handler->refcntr) + && allp->handler->need_signal) + lll_futex_wake (allp->handler->refcntr, 1, LLL_PRIVATE); + + allp = allp->next; + } + } + + return pid; +} +weak_alias (__libc_fork, __fork) +libc_hidden_def (__fork) +weak_alias (__libc_fork, fork) diff --git a/sysdeps/nptl/fork.h b/sysdeps/nptl/fork.h new file mode 100644 index 0000000000..8e28a76098 --- /dev/null +++ b/sysdeps/nptl/fork.h @@ -0,0 +1,59 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include + +/* The fork generation counter, defined in libpthread. */ +extern unsigned long int __fork_generation attribute_hidden; + +/* Pointer to the fork generation counter in the thread library. */ +extern unsigned long int *__fork_generation_pointer attribute_hidden; + +/* Lock to protect allocation and deallocation of fork handlers. */ +extern int __fork_lock attribute_hidden; + +/* Elements of the fork handler lists. */ +struct fork_handler +{ + struct fork_handler *next; + void (*prepare_handler) (void); + void (*parent_handler) (void); + void (*child_handler) (void); + void *dso_handle; + unsigned int refcntr; + int need_signal; +}; + +/* The single linked list of all currently registered for handlers. */ +extern struct fork_handler *__fork_handlers attribute_hidden; + + +/* Function to call to unregister fork handlers. */ +extern void __unregister_atfork (void *dso_handle) attribute_hidden; +#define UNREGISTER_ATFORK(dso_handle) __unregister_atfork (dso_handle) + + +/* C library side function to register new fork handlers. */ +extern int __register_atfork (void (*__prepare) (void), + void (*__parent) (void), + void (*__child) (void), + void *dso_handle); +libc_hidden_proto (__register_atfork) + +/* Add a new element to the fork list. */ +extern void __linkin_atfork (struct fork_handler *newp) attribute_hidden; diff --git a/sysdeps/nptl/jmp-unwind.c b/sysdeps/nptl/jmp-unwind.c new file mode 100644 index 0000000000..b3a960c980 --- /dev/null +++ b/sysdeps/nptl/jmp-unwind.c @@ -0,0 +1,38 @@ +/* Clean up stack frames unwound by longjmp. Linux version. + Copyright (C) 1995-2014 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; if not, see + . */ + +#include +#include +#include + +extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); +#pragma weak __pthread_cleanup_upto + + +void +_longjmp_unwind (jmp_buf env, int val) +{ +#ifdef SHARED + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr___pthread_cleanup_upto, (env->__jmpbuf, + CURRENT_STACK_FRAME)); +#else + if (__pthread_cleanup_upto != NULL) + __pthread_cleanup_upto (env->__jmpbuf, CURRENT_STACK_FRAME); +#endif +} diff --git a/sysdeps/nptl/lowlevellock.h b/sysdeps/nptl/lowlevellock.h new file mode 100644 index 0000000000..7d1913a58d --- /dev/null +++ b/sysdeps/nptl/lowlevellock.h @@ -0,0 +1,83 @@ +/* Low level locking macros used in NPTL implementation. Stub version. + Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include + + +/* Mutex lock counter: + bit 31 clear means unlocked; + bit 31 set means locked. + + All code that looks at bit 31 first increases the 'number of + interested threads' usage counter, which is in bits 0-30. + + All negative mutex values indicate that the mutex is still locked. */ + + +static inline void +__generic_mutex_lock (int *mutex) +{ + unsigned int v; + + /* Bit 31 was clear, we got the mutex. (this is the fastpath). */ + if (atomic_bit_test_set (mutex, 31) == 0) + return; + + atomic_increment (mutex); + + while (1) + { + if (atomic_bit_test_set (mutex, 31) == 0) + { + atomic_decrement (mutex); + return; + } + + /* We have to wait now. First make sure the futex value we are + monitoring is truly negative (i.e. locked). */ + v = *mutex; + if (v >= 0) + continue; + + lll_futex_wait (mutex, v, + // XYZ check mutex flag + LLL_SHARED); + } +} + + +static inline void +__generic_mutex_unlock (int *mutex) +{ + /* Adding 0x80000000 to the counter results in 0 if and only if + there are not other interested threads - we can return (this is + the fastpath). */ + if (atomic_add_zero (mutex, 0x80000000)) + return; + + /* There are other threads waiting for this mutex, wake one of them + up. */ + lll_futex_wake (mutex, 1, + // XYZ check mutex flag + LLL_SHARED); +} + + +#define lll_mutex_lock(futex) __generic_mutex_lock (&(futex)) +#define lll_mutex_unlock(futex) __generic_mutex_unlock (&(futex)) diff --git a/sysdeps/sparc/sparc32/sparcv9/sem_trywait.c b/sysdeps/sparc/sparc32/sparcv9/sem_trywait.c index 80157c5d2a..a8d4acc3f0 100644 --- a/sysdeps/sparc/sparc32/sparcv9/sem_trywait.c +++ b/sysdeps/sparc/sparc32/sparcv9/sem_trywait.c @@ -1 +1 @@ -#include +#include diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index 02eda45067..9ad6d2252b 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -144,6 +144,10 @@ sysdep_headers += bits/initspin.h sysdep_routines += sched_getcpu tests += tst-getcpu + +CFLAGS-fork.c = $(libio-mtsafe) +CFLAGS-getpid.o = -fomit-frame-pointer +CFLAGS-getpid.os = -fomit-frame-pointer endif ifeq ($(subdir),inet) @@ -190,3 +194,7 @@ ifeq ($(subdir),nscd) sysdep-CFLAGS += -DHAVE_EPOLL -DHAVE_SENDFILE -DHAVE_INOTIFY -DHAVE_NETLINK CFLAGS-gai.c += -DNEED_NETLINK endif + +ifeq ($(subdir),nptl) +tests += tst-setgetname +endif diff --git a/sysdeps/unix/sysv/linux/aarch64/sigaction.c b/sysdeps/unix/sysv/linux/aarch64/sigaction.c index 7dabe4689b..ae6c3fde25 100644 --- a/sysdeps/unix/sysv/linux/aarch64/sigaction.c +++ b/sysdeps/unix/sysv/linux/aarch64/sigaction.c @@ -67,12 +67,4 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif - -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction) -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction) -#endif +#include diff --git a/sysdeps/unix/sysv/linux/aio_misc.h b/sysdeps/unix/sysv/linux/aio_misc.h new file mode 100644 index 0000000000..58ac45153f --- /dev/null +++ b/sysdeps/unix/sysv/linux/aio_misc.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2004-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2004. + + 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, see . */ + +#ifndef _AIO_MISC_H +# include_next +# include +# include +# include +# include + +# define aio_start_notify_thread __aio_start_notify_thread +# define aio_create_helper_thread __aio_create_helper_thread + +extern inline void +__aio_start_notify_thread (void) +{ + sigset_t ss; + sigemptyset (&ss); + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); +} + +extern inline int +__aio_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), + void *arg) +{ + pthread_attr_t attr; + + /* Make sure the thread is created detached. */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + + /* The helper thread needs only very little resources. */ + (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); + + /* Block all signals in the helper thread. To do this thoroughly we + temporarily have to block all signals here. */ + sigset_t ss; + sigset_t oss; + sigfillset (&ss); + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); + + int ret = pthread_create (threadp, &attr, tf, arg); + + /* Restore the signal mask. */ + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, + _NSIG / 8); + + (void) pthread_attr_destroy (&attr); + return ret; +} +#endif diff --git a/sysdeps/unix/sysv/linux/allocrtsig.c b/sysdeps/unix/sysv/linux/allocrtsig.c new file mode 100644 index 0000000000..0ed7d089c6 --- /dev/null +++ b/sysdeps/unix/sysv/linux/allocrtsig.c @@ -0,0 +1,55 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include + + +static int current_rtmin = __SIGRTMIN + 2; +static int current_rtmax = __SIGRTMAX; + + +/* We reserve __SIGRTMIN for use as the cancelation signal. This + signal is used internally. */ +int +__libc_current_sigrtmin (void) +{ + return current_rtmin; +} +libc_hidden_def (__libc_current_sigrtmin) +strong_alias (__libc_current_sigrtmin, __libc_current_sigrtmin_private) + + +int +__libc_current_sigrtmax (void) +{ + return current_rtmax; +} +libc_hidden_def (__libc_current_sigrtmax) +strong_alias (__libc_current_sigrtmax, __libc_current_sigrtmax_private) + + +int +__libc_allocate_rtsig (int high) +{ + 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/sysdeps/unix/sysv/linux/alpha/sem_post.c b/sysdeps/unix/sysv/linux/alpha/sem_post.c index befa49723b..9d4495312e 100644 --- a/sysdeps/unix/sysv/linux/alpha/sem_post.c +++ b/sysdeps/unix/sysv/linux/alpha/sem_post.c @@ -2,4 +2,4 @@ the acquire/release semantics of atomic_exchange_and_add. And even if we don't do this, we should be using atomic_full_barrier or otherwise. */ #define __lll_rel_instr "mb" -#include +#include diff --git a/sysdeps/unix/sysv/linux/arm/sigaction.c b/sysdeps/unix/sysv/linux/arm/sigaction.c index 24a2774f8b..8bd2adf7d5 100644 --- a/sysdeps/unix/sysv/linux/arm/sigaction.c +++ b/sysdeps/unix/sysv/linux/arm/sigaction.c @@ -84,12 +84,4 @@ __libc_sigaction (sig, act, oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif - -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction) -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction) -#endif +#include diff --git a/sysdeps/unix/sysv/linux/getpid.c b/sysdeps/unix/sysv/linux/getpid.c new file mode 100644 index 0000000000..937b1d4e11 --- /dev/null +++ b/sysdeps/unix/sysv/linux/getpid.c @@ -0,0 +1,64 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see + . */ + +#include +#include +#include + + +#ifndef NOT_IN_libc +static inline __attribute__((always_inline)) pid_t really_getpid (pid_t oldval); + +static inline __attribute__((always_inline)) pid_t +really_getpid (pid_t oldval) +{ + if (__glibc_likely (oldval == 0)) + { + pid_t selftid = THREAD_GETMEM (THREAD_SELF, tid); + if (__glibc_likely (selftid != 0)) + return selftid; + } + + INTERNAL_SYSCALL_DECL (err); + pid_t result = INTERNAL_SYSCALL (getpid, err, 0); + + /* We do not set the PID field in the TID here since we might be + called from a signal handler while the thread executes fork. */ + if (oldval == 0) + THREAD_SETMEM (THREAD_SELF, tid, result); + return result; +} +#endif + +pid_t +__getpid (void) +{ +#ifdef NOT_IN_libc + INTERNAL_SYSCALL_DECL (err); + pid_t result = INTERNAL_SYSCALL (getpid, err, 0); +#else + pid_t result = THREAD_GETMEM (THREAD_SELF, pid); + if (__glibc_unlikely (result <= 0)) + result = really_getpid (result); +#endif + return result; +} + +libc_hidden_def (__getpid) +weak_alias (__getpid, getpid) +libc_hidden_def (getpid) diff --git a/sysdeps/unix/sysv/linux/i386/sigaction.c b/sysdeps/unix/sysv/linux/i386/sigaction.c index 778037aee8..b0e71057ad 100644 --- a/sysdeps/unix/sysv/linux/i386/sigaction.c +++ b/sysdeps/unix/sysv/linux/i386/sigaction.c @@ -84,15 +84,7 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif - -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction) -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction) -#endif +#include /* NOTE: Please think twice before making any changes to the bits of code below. GDB needs some intimate knowledge about it to diff --git a/sysdeps/unix/sysv/linux/ia64/fork.S b/sysdeps/unix/sysv/linux/ia64/fork.S deleted file mode 100644 index 496d0b7eff..0000000000 --- a/sysdeps/unix/sysv/linux/ia64/fork.S +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 2000-2014 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; if not, see - . */ - - -#include -#define _SIGNAL_H -#include - -/* pid_t fork(void); */ -/* Implemented as a clone system call with parameters SIGCHLD and 0 */ - -ENTRY(__libc_fork) - alloc r2=ar.pfs,0,0,2,0 - mov out0=SIGCHLD /* Return SIGCHLD when child finishes */ - /* no other clone flags; nothing shared */ - mov out1=0 /* Standard sp value. */ - ;; - DO_CALL (SYS_ify (clone)) - cmp.eq p6,p0=-1,r10 -(p6) br.cond.spnt.few __syscall_error - ret -PSEUDO_END(__libc_fork) - -weak_alias (__libc_fork, __fork) -libc_hidden_def (__fork) -weak_alias (__libc_fork, fork) diff --git a/sysdeps/unix/sysv/linux/ia64/sigaction.c b/sysdeps/unix/sysv/linux/ia64/sigaction.c index 97f7f499be..2033f11a45 100644 --- a/sysdeps/unix/sysv/linux/ia64/sigaction.c +++ b/sysdeps/unix/sysv/linux/ia64/sigaction.c @@ -45,12 +45,4 @@ __libc_sigaction (sig, act, oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif - -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction) -libc_hidden_def (__sigaction) -weak_alias (__libc_sigaction, sigaction) -#endif +#include diff --git a/sysdeps/unix/sysv/linux/kernel-posix-timers.h b/sysdeps/unix/sysv/linux/kernel-posix-timers.h new file mode 100644 index 0000000000..532da55e14 --- /dev/null +++ b/sysdeps/unix/sysv/linux/kernel-posix-timers.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see . */ + +#include +#include +#include +#include + + +/* Nonzero if the system calls are not available. */ +extern int __no_posix_timers attribute_hidden; + +/* Callback to start helper thread. */ +extern void __start_helper_thread (void) attribute_hidden; + +/* Control variable for helper thread creation. */ +extern pthread_once_t __helper_once attribute_hidden; + +/* TID of the helper thread. */ +extern pid_t __helper_tid attribute_hidden; + +/* List of active SIGEV_THREAD timers. */ +extern struct timer *__active_timer_sigev_thread attribute_hidden; +/* Lock for the __active_timer_sigev_thread. */ +extern pthread_mutex_t __active_timer_sigev_thread_lock attribute_hidden; + + +/* Type of timers in the kernel. */ +typedef int kernel_timer_t; + + +/* Internal representation of timer. */ +struct timer +{ + /* Notification mechanism. */ + int sigev_notify; + + /* Timer ID returned by the kernel. */ + kernel_timer_t ktimerid; + + /* All new elements must be added after ktimerid. And if the thrfunc + element is not the third element anymore the memory allocation in + timer_create needs to be changed. */ + + /* Parameters for the thread to be started for SIGEV_THREAD. */ + void (*thrfunc) (sigval_t); + sigval_t sival; + pthread_attr_t attr; + + /* Next element in list of active SIGEV_THREAD timers. */ + struct timer *next; +}; diff --git a/sysdeps/unix/sysv/linux/mips/sigaction.c b/sysdeps/unix/sysv/linux/mips/sigaction.c index 6b808a6cdf..90b1a3b13d 100644 --- a/sysdeps/unix/sysv/linux/mips/sigaction.c +++ b/sysdeps/unix/sysv/linux/mips/sigaction.c @@ -87,15 +87,8 @@ __libc_sigaction (sig, act, oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif +#include -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction) -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction) -#endif /* NOTE: Please think twice before making any changes to the bits of code below. GDB needs some intimate knowledge about it to diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c index a61839f507..d50a9f2d57 100644 --- a/sysdeps/unix/sysv/linux/mq_notify.c +++ b/sysdeps/unix/sysv/linux/mq_notify.c @@ -1,5 +1,6 @@ /* Copyright (C) 2004-2014 Free Software Foundation, Inc. This file is part of the GNU C Library. + Contribute by Ulrich Drepper , 2004. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -15,27 +16,265 @@ License along with the GNU C Library; if not, see . */ +#include #include +#include #include -#include +#include +#include +#include +#include #include +#include +#include +#include +#include + #ifdef __NR_mq_notify +/* Defined in the kernel headers: */ +#define NOTIFY_COOKIE_LEN 32 /* Length of the cookie used. */ +#define NOTIFY_WOKENUP 1 /* Code for notifcation. */ +#define NOTIFY_REMOVED 2 /* Code for closed message queue + of de-notifcation. */ + + +/* Data structure for the queued notification requests. */ +union notify_data +{ + struct + { + void (*fct) (union sigval); /* The function to run. */ + union sigval param; /* The parameter to pass. */ + pthread_attr_t *attr; /* Attributes to create the thread with. */ + /* NB: on 64-bit machines the struct as a size of 24 bytes. Which means + byte 31 can still be used for returning the status. */ + }; + char raw[NOTIFY_COOKIE_LEN]; +}; + + +/* Keep track of the initialization. */ +static pthread_once_t once = PTHREAD_ONCE_INIT; + + +/* The netlink socket. */ +static int netlink_socket = -1; + + +/* Barrier used to make sure data passed to the new thread is not + resused by the parent. */ +static pthread_barrier_t notify_barrier; + + +/* Modify the signal mask. We move this into a separate function so + that the stack space needed for sigset_t is not deducted from what + the thread can use. */ +static int +__attribute__ ((noinline)) +change_sigmask (int how, sigset_t *oss) +{ + sigset_t ss; + sigfillset (&ss); + return pthread_sigmask (how, &ss, oss); +} + + +/* The function used for the notification. */ +static void * +notification_function (void *arg) +{ + /* Copy the function and parameter so that the parent thread can go + on with its life. */ + volatile union notify_data *data = (volatile union notify_data *) arg; + void (*fct) (union sigval) = data->fct; + union sigval param = data->param; + + /* Let the parent go. */ + (void) pthread_barrier_wait (¬ify_barrier); + + /* Make the thread detached. */ + (void) pthread_detach (pthread_self ()); + + /* The parent thread has all signals blocked. This is probably a + bit surprising for this thread. So we unblock all of them. */ + (void) change_sigmask (SIG_UNBLOCK, NULL); + + /* Now run the user code. */ + fct (param); + + /* And we are done. */ + return NULL; +} + + +/* Helper thread. */ +static void * +helper_thread (void *arg) +{ + while (1) + { + union notify_data data; + + ssize_t n = recv (netlink_socket, &data, sizeof (data), + MSG_NOSIGNAL | MSG_WAITALL); + if (n < NOTIFY_COOKIE_LEN) + continue; + + if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_WOKENUP) + { + /* Just create the thread as instructed. There is no way to + report a problem with creating a thread. */ + pthread_t th; + if (__builtin_expect (pthread_create (&th, data.attr, + notification_function, &data) + == 0, 0)) + /* Since we passed a pointer to DATA to the new thread we have + to wait until it is done with it. */ + (void) pthread_barrier_wait (¬ify_barrier); + } + else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED) + /* The only state we keep is the copy of the thread attributes. */ + free (data.attr); + } + return NULL; +} + + +static void +reset_once (void) +{ + once = PTHREAD_ONCE_INIT; +} + + +static void +init_mq_netlink (void) +{ + /* This code might be called a second time after fork(). The file + descriptor is inherited from the parent. */ + if (netlink_socket == -1) + { + /* Just a normal netlink socket, not bound. */ + netlink_socket = socket (AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, 0); + /* No need to do more if we have no socket. */ + if (netlink_socket == -1) + return; + } + + int err = 1; + + /* Initialize the barrier. */ + if (__builtin_expect (pthread_barrier_init (¬ify_barrier, NULL, 2) == 0, + 0)) + { + /* Create the helper thread. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + /* We do not need much stack space, the bare minimum will be enough. */ + (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); + + /* Temporarily block all signals so that the newly created + thread inherits the mask. */ + sigset_t oss; + int have_no_oss = change_sigmask (SIG_BLOCK, &oss); + + pthread_t th; + err = pthread_create (&th, &attr, helper_thread, NULL); + + /* Reset the signal mask. */ + if (!have_no_oss) + pthread_sigmask (SIG_SETMASK, &oss, NULL); + + (void) pthread_attr_destroy (&attr); + + if (err == 0) + { + static int added_atfork; + + if (added_atfork == 0 + && pthread_atfork (NULL, NULL, reset_once) != 0) + { + /* The child thread will call recv() which is a + cancellation point. */ + (void) pthread_cancel (th); + err = 1; + } + else + added_atfork = 1; + } + } + + if (err != 0) + { + close_not_cancel_no_status (netlink_socket); + netlink_socket = -1; + } +} + + /* Register notification upon message arrival to an empty message queue MQDES. */ int mq_notify (mqd_t mqdes, const struct sigevent *notification) { - /* mq_notify which handles SIGEV_THREAD is included in the thread - add-on. */ - if (notification != NULL - && notification->sigev_notify == SIGEV_THREAD) + /* Make sure the type is correctly defined. */ + assert (sizeof (union notify_data) == NOTIFY_COOKIE_LEN); + + /* Special treatment needed for SIGEV_THREAD. */ + if (notification == NULL || notification->sigev_notify != SIGEV_THREAD) + return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); + + /* The kernel cannot directly start threads. This will have to be + done at userlevel. Since we cannot start threads from signal + handlers we have to create a dedicated thread which waits for + notifications for arriving messages and creates threads in + response. */ + + /* Initialize only once. */ + pthread_once (&once, init_mq_netlink); + + /* If we cannot create the netlink socket we cannot provide + SIGEV_THREAD support. */ + if (__glibc_unlikely (netlink_socket == -1)) { __set_errno (ENOSYS); return -1; } - return INLINE_SYSCALL (mq_notify, 2, mqdes, notification); + + /* Create the cookie. It will hold almost all the state. */ + union notify_data data; + memset (&data, '\0', sizeof (data)); + data.fct = notification->sigev_notify_function; + data.param = notification->sigev_value; + + if (notification->sigev_notify_attributes != NULL) + { + /* The thread attribute has to be allocated separately. */ + data.attr = (pthread_attr_t *) malloc (sizeof (pthread_attr_t)); + if (data.attr == NULL) + return -1; + + memcpy (data.attr, notification->sigev_notify_attributes, + sizeof (pthread_attr_t)); + } + + /* Construct the new request. */ + struct sigevent se; + se.sigev_notify = SIGEV_THREAD; + se.sigev_signo = netlink_socket; + se.sigev_value.sival_ptr = &data; + + /* Tell the kernel. */ + int retval = INLINE_SYSCALL (mq_notify, 2, mqdes, &se); + + /* If it failed, free the allocated memory. */ + if (__glibc_unlikely (retval != 0)) + free (data.attr); + + return retval; } #else diff --git a/sysdeps/unix/sysv/linux/pt-raise.c b/sysdeps/unix/sysv/linux/pt-raise.c new file mode 100644 index 0000000000..fc26e858b3 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pt-raise.c @@ -0,0 +1,38 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include +#include +#include +#include + + +int +raise (sig) + int sig; +{ + /* raise is an async-safe function. It could be called while the + fork function temporarily invalidated the PID field. Adjust for + that. */ + pid_t pid = THREAD_GETMEM (THREAD_SELF, pid); + if (__glibc_unlikely (pid < 0)) + pid = -pid; + + return INLINE_SYSCALL (tgkill, 3, pid, THREAD_GETMEM (THREAD_SELF, tid), + sig); +} diff --git a/sysdeps/unix/sysv/linux/pthread_getaffinity.c b/sysdeps/unix/sysv/linux/pthread_getaffinity.c new file mode 100644 index 0000000000..f58e9cc3e9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pthread_getaffinity.c @@ -0,0 +1,59 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include + + +int +__pthread_getaffinity_new (pthread_t th, size_t cpusetsize, cpu_set_t *cpuset) +{ + const struct pthread *pd = (const struct pthread *) th; + + INTERNAL_SYSCALL_DECL (err); + int res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, pd->tid, + MIN (INT_MAX, cpusetsize), cpuset); + if (INTERNAL_SYSCALL_ERROR_P (res, err)) + return INTERNAL_SYSCALL_ERRNO (res, err); + + /* Clean the rest of the memory the kernel didn't do. */ + memset ((char *) cpuset + res, '\0', cpusetsize - res); + + return 0; +} +strong_alias (__pthread_getaffinity_new, __pthread_getaffinity_np) +versioned_symbol (libpthread, __pthread_getaffinity_new, + pthread_getaffinity_np, GLIBC_2_3_4); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) +int +__pthread_getaffinity_old (pthread_t th, cpu_set_t *cpuset) +{ + /* The old interface by default assumed a 1024 processor bitmap. */ + return __pthread_getaffinity_new (th, 128, cpuset); +} +compat_symbol (libpthread, __pthread_getaffinity_old, pthread_getaffinity_np, + GLIBC_2_3_3); +#endif diff --git a/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c b/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c new file mode 100644 index 0000000000..3e634a03c8 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pthread_getcpuclockid.c @@ -0,0 +1,44 @@ +/* pthread_getcpuclockid -- Get POSIX clockid_t for a pthread_t. Linux version + Copyright (C) 2000-2014 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, see . */ + +#include +#include +#include +#include +#include + + +int +pthread_getcpuclockid (threadid, clockid) + pthread_t threadid; + clockid_t *clockid; +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* The clockid_t value is a simple computation from the TID. */ + + const clockid_t tidclock = MAKE_THREAD_CPUCLOCK (pd->tid, CPUCLOCK_SCHED); + + *clockid = tidclock; + return 0; +} diff --git a/sysdeps/unix/sysv/linux/pthread_getname.c b/sysdeps/unix/sysv/linux/pthread_getname.c new file mode 100644 index 0000000000..e5a319a3e1 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pthread_getname.c @@ -0,0 +1,72 @@ +/* pthread_getname_np -- Get thread name. Linux version + Copyright (C) 2010-2014 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, see . */ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +int +pthread_getname_np (th, buf, len) + pthread_t th; + char *buf; + size_t len; +{ + const struct pthread *pd = (const struct pthread *) th; + + /* Unfortunately the kernel headers do not export the TASK_COMM_LEN + macro. So we have to define it here. */ +#define TASK_COMM_LEN 16 + if (len < TASK_COMM_LEN) + return ERANGE; + + if (pd == THREAD_SELF) + return prctl (PR_GET_NAME, buf) ? errno : 0; + +#define FMT "/proc/self/task/%u/comm" + char fname[sizeof (FMT) + 8]; + sprintf (fname, FMT, (unsigned int) pd->tid); + + int fd = open_not_cancel_2 (fname, O_RDONLY); + if (fd == -1) + return errno; + + int res = 0; + ssize_t n = TEMP_FAILURE_RETRY (read_not_cancel (fd, buf, len)); + if (n < 0) + res = errno; + else + { + if (buf[n - 1] == '\n') + buf[n - 1] = '\0'; + else if (n == len) + res = ERANGE; + else + buf[n] = '\0'; + } + + close_not_cancel_no_status (fd); + + return res; +} diff --git a/sysdeps/unix/sysv/linux/pthread_kill.c b/sysdeps/unix/sysv/linux/pthread_kill.c new file mode 100644 index 0000000000..0a4d8627a9 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pthread_kill.c @@ -0,0 +1,66 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include +#include +#include +#include +#include + + +int +__pthread_kill (threadid, signo) + pthread_t threadid; + int signo; +{ + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__glibc_unlikely (tid <= 0)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Disallow sending the signal we use for cancellation, timers, + for the setxid implementation. */ + if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) + return EINVAL; + + /* We have a special syscall to do the work. */ + INTERNAL_SYSCALL_DECL (err); + + /* One comment: The PID field in the TCB can temporarily be changed + (in fork). But this must not affect this code here. Since this + function would have to be called while the thread is executing + fork, it would have to happen in a signal handler. But this is + no allowed, pthread_kill is not guaranteed to be async-safe. */ + int val; + val = INTERNAL_SYSCALL (tgkill, err, 3, THREAD_GETMEM (THREAD_SELF, pid), + tid, signo); + + return (INTERNAL_SYSCALL_ERROR_P (val, err) + ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); +} +strong_alias (__pthread_kill, pthread_kill) diff --git a/sysdeps/unix/sysv/linux/pthread_setaffinity.c b/sysdeps/unix/sysv/linux/pthread_setaffinity.c new file mode 100644 index 0000000000..874cf4b578 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pthread_setaffinity.c @@ -0,0 +1,104 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see + . */ + +#include +#include +#include +#include +#include +#include + + +size_t __kernel_cpumask_size attribute_hidden; + + +/* Determine the current affinity. As a side affect we learn + about the size of the cpumask_t in the kernel. */ +int +__determine_cpumask_size (pid_t tid) +{ + INTERNAL_SYSCALL_DECL (err); + int res; + + size_t psize = 128; + void *p = alloca (psize); + + while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, tid, psize, p), + INTERNAL_SYSCALL_ERROR_P (res, err) + && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) + p = extend_alloca (p, psize, 2 * psize); + + if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err)) + return INTERNAL_SYSCALL_ERRNO (res, err); + + __kernel_cpumask_size = res; + + return 0; +} + + +int +__pthread_setaffinity_new (pthread_t th, size_t cpusetsize, + const cpu_set_t *cpuset) +{ + const struct pthread *pd = (const struct pthread *) th; + + INTERNAL_SYSCALL_DECL (err); + int res; + + if (__glibc_unlikely (__kernel_cpumask_size == 0)) + { + res = __determine_cpumask_size (pd->tid); + if (res != 0) + return res; + } + + /* We now know the size of the kernel cpumask_t. Make sure the user + does not request to set a bit beyond that. */ + for (size_t cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt) + if (((char *) cpuset)[cnt] != '\0') + /* Found a nonzero byte. This means the user request cannot be + fulfilled. */ + return EINVAL; + + res = INTERNAL_SYSCALL (sched_setaffinity, err, 3, pd->tid, cpusetsize, + cpuset); + +#ifdef RESET_VGETCPU_CACHE + if (!INTERNAL_SYSCALL_ERROR_P (res, err)) + RESET_VGETCPU_CACHE (); +#endif + + return (INTERNAL_SYSCALL_ERROR_P (res, err) + ? INTERNAL_SYSCALL_ERRNO (res, err) + : 0); +} +versioned_symbol (libpthread, __pthread_setaffinity_new, + pthread_setaffinity_np, GLIBC_2_3_4); + + +#if SHLIB_COMPAT (libpthread, GLIBC_2_3_3, GLIBC_2_3_4) +int +__pthread_setaffinity_old (pthread_t th, cpu_set_t *cpuset) +{ + /* The old interface by default assumed a 1024 processor bitmap. */ + return __pthread_setaffinity_new (th, 128, cpuset); +} +compat_symbol (libpthread, __pthread_setaffinity_old, pthread_setaffinity_np, + GLIBC_2_3_3); +#endif diff --git a/sysdeps/unix/sysv/linux/pthread_setname.c b/sysdeps/unix/sysv/linux/pthread_setname.c new file mode 100644 index 0000000000..409560e586 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pthread_setname.c @@ -0,0 +1,65 @@ +/* pthread_setname_np -- Set thread name. Linux version + Copyright (C) 2010-2014 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, see . */ + +#include +#include +#include +#include +#include +#include +#include + +#include + + +int +pthread_setname_np (th, name) + pthread_t th; + const char *name; +{ + const struct pthread *pd = (const struct pthread *) th; + + /* Unfortunately the kernel headers do not export the TASK_COMM_LEN + macro. So we have to define it here. */ +#define TASK_COMM_LEN 16 + size_t name_len = strlen (name); + if (name_len >= TASK_COMM_LEN) + return ERANGE; + + if (pd == THREAD_SELF) + return prctl (PR_SET_NAME, name) ? errno : 0; + +#define FMT "/proc/self/task/%u/comm" + char fname[sizeof (FMT) + 8]; + sprintf (fname, FMT, (unsigned int) pd->tid); + + int fd = open_not_cancel_2 (fname, O_RDWR); + if (fd == -1) + return errno; + + int res = 0; + ssize_t n = TEMP_FAILURE_RETRY (write_not_cancel (fd, name, name_len)); + if (n < 0) + res = errno; + else if (n != name_len) + res = EIO; + + close_not_cancel_no_status (fd); + + return res; +} diff --git a/sysdeps/unix/sysv/linux/pthread_sigqueue.c b/sysdeps/unix/sysv/linux/pthread_sigqueue.c new file mode 100644 index 0000000000..1e66815416 --- /dev/null +++ b/sysdeps/unix/sysv/linux/pthread_sigqueue.c @@ -0,0 +1,81 @@ +/* Copyright (C) 2009-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2009. + + 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, see + . */ + +#include +#include +#include +#include +#include +#include +#include + + +int +pthread_sigqueue (threadid, signo, value) + pthread_t threadid; + int signo; + const union sigval value; +{ +#ifdef __NR_rt_tgsigqueueinfo + struct pthread *pd = (struct pthread *) threadid; + + /* Make sure the descriptor is valid. */ + if (DEBUGGING_P && INVALID_TD_P (pd)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Force load of pd->tid into local variable or register. Otherwise + if a thread exits between ESRCH test and tgkill, we might return + EINVAL, because pd->tid would be cleared by the kernel. */ + pid_t tid = atomic_forced_read (pd->tid); + if (__glibc_unlikely (tid <= 0)) + /* Not a valid thread handle. */ + return ESRCH; + + /* Disallow sending the signal we use for cancellation, timers, + for the setxid implementation. */ + if (signo == SIGCANCEL || signo == SIGTIMER || signo == SIGSETXID) + return EINVAL; + + /* Set up the siginfo_t structure. */ + siginfo_t info; + memset (&info, '\0', sizeof (siginfo_t)); + info.si_signo = signo; + info.si_code = SI_QUEUE; + info.si_pid = THREAD_GETMEM (THREAD_SELF, pid); + info.si_uid = getuid (); + info.si_value = value; + + /* We have a special syscall to do the work. */ + INTERNAL_SYSCALL_DECL (err); + + /* One comment: The PID field in the TCB can temporarily be changed + (in fork). But this must not affect this code here. Since this + function would have to be called while the thread is executing + fork, it would have to happen in a signal handler. But this is + no allowed, pthread_sigqueue is not guaranteed to be async-safe. */ + int val = INTERNAL_SYSCALL (rt_tgsigqueueinfo, err, 4, + THREAD_GETMEM (THREAD_SELF, pid), + tid, signo, &info); + + return (INTERNAL_SYSCALL_ERROR_P (val, err) + ? INTERNAL_SYSCALL_ERRNO (val, err) : 0); +#else + return ENOSYS; +#endif +} diff --git a/sysdeps/unix/sysv/linux/raise.c b/sysdeps/unix/sysv/linux/raise.c new file mode 100644 index 0000000000..4106e8c458 --- /dev/null +++ b/sysdeps/unix/sysv/linux/raise.c @@ -0,0 +1,58 @@ +/* Copyright (C) 2002-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 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, see + . */ + +#include +#include +#include +#include +#include + + +int +raise (sig) + int sig; +{ + struct pthread *pd = THREAD_SELF; + pid_t pid = THREAD_GETMEM (pd, pid); + pid_t selftid = THREAD_GETMEM (pd, tid); + if (selftid == 0) + { + /* This system call is not supposed to fail. */ +#ifdef INTERNAL_SYSCALL + INTERNAL_SYSCALL_DECL (err); + selftid = INTERNAL_SYSCALL (gettid, err, 0); +#else + selftid = INLINE_SYSCALL (gettid, 0); +#endif + THREAD_SETMEM (pd, tid, selftid); + + /* We do not set the PID field in the TID here since we might be + called from a signal handler while the thread executes fork. */ + pid = selftid; + } + else + /* raise is an async-safe function. It could be called while the + fork/vfork function temporarily invalidated the PID field. Adjust for + that. */ + if (__glibc_unlikely (pid <= 0)) + pid = (pid & INT_MAX) == 0 ? selftid : -pid; + + return INLINE_SYSCALL (tgkill, 3, pid, selftid, sig); +} +libc_hidden_def (raise) +weak_alias (raise, gsignal) diff --git a/sysdeps/unix/sysv/linux/s390/jmp-unwind.c b/sysdeps/unix/sysv/linux/s390/jmp-unwind.c index f35eab5ac1..32226bc593 100644 --- a/sysdeps/unix/sysv/linux/s390/jmp-unwind.c +++ b/sysdeps/unix/sysv/linux/s390/jmp-unwind.c @@ -18,7 +18,7 @@ #include #include -#include +#include extern void __pthread_cleanup_upto (__jmp_buf env, char *targetframe); #pragma weak __pthread_cleanup_upto diff --git a/sysdeps/unix/sysv/linux/s390/pthread_mutex_cond_lock.c b/sysdeps/unix/sysv/linux/s390/pthread_mutex_cond_lock.c index 6fc0f969ef..aa6cf9a79e 100644 --- a/sysdeps/unix/sysv/linux/s390/pthread_mutex_cond_lock.c +++ b/sysdeps/unix/sysv/linux/s390/pthread_mutex_cond_lock.c @@ -19,4 +19,4 @@ already elided locks. */ #include -#include +#include diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c b/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c index e9a984b5af..995afbc2fc 100644 --- a/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c +++ b/sysdeps/unix/sysv/linux/s390/s390-64/sigaction.c @@ -43,12 +43,4 @@ __libc_sigaction (sig, act, oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif - -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction) -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction) -#endif +#include diff --git a/sysdeps/unix/sysv/linux/sigaction.c b/sysdeps/unix/sysv/linux/sigaction.c index eaa517577f..c8694c17e3 100644 --- a/sysdeps/unix/sysv/linux/sigaction.c +++ b/sysdeps/unix/sysv/linux/sigaction.c @@ -69,12 +69,4 @@ __libc_sigaction (sig, act, oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif - -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction) -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction) -#endif +#include diff --git a/sysdeps/unix/sysv/linux/sigtimedwait.c b/sysdeps/unix/sysv/linux/sigtimedwait.c index 5491b480ea..c7727cf4c6 100644 --- a/sysdeps/unix/sysv/linux/sigtimedwait.c +++ b/sysdeps/unix/sysv/linux/sigtimedwait.c @@ -19,6 +19,7 @@ #include #include +#include #include #include diff --git a/sysdeps/unix/sysv/linux/sigwait.c b/sysdeps/unix/sysv/linux/sigwait.c index 26528227e6..b7ac868bb5 100644 --- a/sysdeps/unix/sysv/linux/sigwait.c +++ b/sysdeps/unix/sysv/linux/sigwait.c @@ -21,6 +21,7 @@ #include #include +#include #include #include diff --git a/sysdeps/unix/sysv/linux/sigwaitinfo.c b/sysdeps/unix/sysv/linux/sigwaitinfo.c index 9218afc551..fa9b0b73db 100644 --- a/sysdeps/unix/sysv/linux/sigwaitinfo.c +++ b/sysdeps/unix/sysv/linux/sigwaitinfo.c @@ -21,6 +21,7 @@ #include #include +#include #include #include diff --git a/sysdeps/unix/sysv/linux/sleep.c b/sysdeps/unix/sysv/linux/sleep.c index 3b352c68bc..5411fd5e98 100644 --- a/sysdeps/unix/sysv/linux/sleep.c +++ b/sysdeps/unix/sysv/linux/sleep.c @@ -23,6 +23,7 @@ #include /* For the real memset prototype. */ #include #include +#include #if 0 diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c index 5e8cf69800..a54d532c85 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/sigaction.c @@ -62,15 +62,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif +#include -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction); -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction); -#endif static void __rt_sigreturn_stub (void) diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c index 665e658cf9..514dabfe50 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/sigaction.c @@ -63,15 +63,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif +#include -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction); -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction); -#endif static void __rt_sigreturn_stub (void) diff --git a/sysdeps/unix/sysv/linux/syscalls.list b/sysdeps/unix/sysv/linux/syscalls.list index 2e6cf9c60d..d639d63cf9 100644 --- a/sysdeps/unix/sysv/linux/syscalls.list +++ b/sysdeps/unix/sysv/linux/syscalls.list @@ -15,7 +15,6 @@ epoll_ctl EXTRA epoll_ctl i:iiip epoll_ctl epoll_wait EXTRA epoll_wait Ci:ipii epoll_wait fdatasync - fdatasync Ci:i fdatasync flock - flock i:ii __flock flock -fork - fork i: __libc_fork __fork fork get_kernel_syms EXTRA get_kernel_syms i:p get_kernel_syms getegid - getegid Ei: __getegid getegid geteuid - geteuid Ei: __geteuid geteuid diff --git a/sysdeps/unix/sysv/linux/timer_create.c b/sysdeps/unix/sysv/linux/timer_create.c new file mode 100644 index 0000000000..e5c056bf2c --- /dev/null +++ b/sysdeps/unix/sysv/linux/timer_create.c @@ -0,0 +1,179 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "kernel-posix-timers.h" +#include "kernel-posix-cpu-timers.h" + + +#ifdef timer_create_alias +# define timer_create timer_create_alias +#endif + + +int +timer_create (clock_id, evp, timerid) + clockid_t clock_id; + struct sigevent *evp; + timer_t *timerid; +{ +#undef timer_create + { + clockid_t syscall_clockid = (clock_id == CLOCK_PROCESS_CPUTIME_ID + ? MAKE_PROCESS_CPUCLOCK (0, CPUCLOCK_SCHED) + : clock_id == CLOCK_THREAD_CPUTIME_ID + ? MAKE_THREAD_CPUCLOCK (0, CPUCLOCK_SCHED) + : clock_id); + + /* If the user wants notification via a thread we need to handle + this special. */ + if (evp == NULL + || __builtin_expect (evp->sigev_notify != SIGEV_THREAD, 1)) + { + struct sigevent local_evp; + + /* We avoid allocating too much memory by basically + using struct timer as a derived class with the + first two elements being in the superclass. We only + need these two elements here. */ + struct timer *newp = (struct timer *) malloc (offsetof (struct timer, + thrfunc)); + if (newp == NULL) + /* No more memory. */ + return -1; + + if (evp == NULL) + { + /* The kernel has to pass up the timer ID which is a + userlevel object. Therefore we cannot leave it up to + the kernel to determine it. */ + local_evp.sigev_notify = SIGEV_SIGNAL; + local_evp.sigev_signo = SIGALRM; + local_evp.sigev_value.sival_ptr = newp; + + evp = &local_evp; + } + + kernel_timer_t ktimerid; + int retval = INLINE_SYSCALL (timer_create, 3, syscall_clockid, evp, + &ktimerid); + + if (retval != -1) + { + newp->sigev_notify = (evp != NULL + ? evp->sigev_notify : SIGEV_SIGNAL); + newp->ktimerid = ktimerid; + + *timerid = (timer_t) newp; + } + else + { + /* Cannot allocate the timer, fail. */ + free (newp); + retval = -1; + } + + return retval; + } + else + { + /* Create the helper thread. */ + pthread_once (&__helper_once, __start_helper_thread); + if (__helper_tid == 0) + { + /* No resources to start the helper thread. */ + __set_errno (EAGAIN); + return -1; + } + + struct timer *newp; + newp = (struct timer *) malloc (sizeof (struct timer)); + if (newp == NULL) + return -1; + + /* Copy the thread parameters the user provided. */ + newp->sival = evp->sigev_value; + newp->thrfunc = evp->sigev_notify_function; + newp->sigev_notify = SIGEV_THREAD; + + /* We cannot simply copy the thread attributes since the + implementation might keep internal information for + each instance. */ + (void) pthread_attr_init (&newp->attr); + if (evp->sigev_notify_attributes != NULL) + { + struct pthread_attr *nattr; + struct pthread_attr *oattr; + + nattr = (struct pthread_attr *) &newp->attr; + oattr = (struct pthread_attr *) evp->sigev_notify_attributes; + + nattr->schedparam = oattr->schedparam; + nattr->schedpolicy = oattr->schedpolicy; + nattr->flags = oattr->flags; + nattr->guardsize = oattr->guardsize; + nattr->stackaddr = oattr->stackaddr; + nattr->stacksize = oattr->stacksize; + } + + /* In any case set the detach flag. */ + (void) pthread_attr_setdetachstate (&newp->attr, + PTHREAD_CREATE_DETACHED); + + /* Create the event structure for the kernel timer. */ + struct sigevent sev = + { .sigev_value.sival_ptr = newp, + .sigev_signo = SIGTIMER, + .sigev_notify = SIGEV_SIGNAL | SIGEV_THREAD_ID, + ._sigev_un = { ._pad = { [0] = __helper_tid } } }; + + /* Create the timer. */ + INTERNAL_SYSCALL_DECL (err); + int res; + res = INTERNAL_SYSCALL (timer_create, err, 3, + syscall_clockid, &sev, &newp->ktimerid); + if (! INTERNAL_SYSCALL_ERROR_P (res, err)) + { + /* Add to the queue of active timers with thread + delivery. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + newp->next = __active_timer_sigev_thread; + __active_timer_sigev_thread = newp; + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + + *timerid = (timer_t) newp; + return 0; + } + + /* Free the resources. */ + free (newp); + + __set_errno (INTERNAL_SYSCALL_ERRNO (res, err)); + + return -1; + } + } +} diff --git a/sysdeps/unix/sysv/linux/timer_delete.c b/sysdeps/unix/sysv/linux/timer_delete.c new file mode 100644 index 0000000000..1de81236e2 --- /dev/null +++ b/sysdeps/unix/sysv/linux/timer_delete.c @@ -0,0 +1,73 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see . */ + +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +#ifdef timer_delete_alias +# define timer_delete timer_delete_alias +#endif + + +int +timer_delete (timerid) + timer_t timerid; +{ +#undef timer_delete + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_delete, 1, kt->ktimerid); + + if (res == 0) + { + if (kt->sigev_notify == SIGEV_THREAD) + { + /* Remove the timer from the list. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + if (__active_timer_sigev_thread == kt) + __active_timer_sigev_thread = kt->next; + else + { + struct timer *prevp = __active_timer_sigev_thread; + while (prevp->next != NULL) + if (prevp->next == kt) + { + prevp->next = kt->next; + break; + } + else + prevp = prevp->next; + } + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + } + + /* Free the memory. */ + (void) free (kt); + + return 0; + } + + /* The kernel timer is not known or something else bad happened. + Return the error. */ + return -1; +} diff --git a/sysdeps/unix/sysv/linux/timer_getoverr.c b/sysdeps/unix/sysv/linux/timer_getoverr.c new file mode 100644 index 0000000000..0ac394114e --- /dev/null +++ b/sysdeps/unix/sysv/linux/timer_getoverr.c @@ -0,0 +1,41 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see . */ + +#include +#include +#include +#include "kernel-posix-timers.h" + + +#ifdef timer_getoverrun_alias +# define timer_getoverrun timer_getoverrun_alias +#endif + + +int +timer_getoverrun (timerid) + timer_t timerid; +{ +#undef timer_getoverrun + struct timer *kt = (struct timer *) timerid; + + /* Get the information from the kernel. */ + int res = INLINE_SYSCALL (timer_getoverrun, 1, kt->ktimerid); + + return res; +} diff --git a/sysdeps/unix/sysv/linux/timer_gettime.c b/sysdeps/unix/sysv/linux/timer_gettime.c new file mode 100644 index 0000000000..7783034a76 --- /dev/null +++ b/sysdeps/unix/sysv/linux/timer_gettime.c @@ -0,0 +1,43 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see . */ + +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +#ifdef timer_gettime_alias +# define timer_gettime timer_gettime_alias +#endif + + +int +timer_gettime (timerid, value) + timer_t timerid; + struct itimerspec *value; +{ +#undef timer_gettime + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_gettime, 2, kt->ktimerid, value); + + return res; +} diff --git a/sysdeps/unix/sysv/linux/timer_routines.c b/sysdeps/unix/sysv/linux/timer_routines.c new file mode 100644 index 0000000000..4ac9bbe896 --- /dev/null +++ b/sysdeps/unix/sysv/linux/timer_routines.c @@ -0,0 +1,196 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see . */ + +#include +#include +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +/* List of active SIGEV_THREAD timers. */ +struct timer *__active_timer_sigev_thread; +/* Lock for the __active_timer_sigev_thread. */ +pthread_mutex_t __active_timer_sigev_thread_lock = PTHREAD_MUTEX_INITIALIZER; + + +struct thread_start_data +{ + void (*thrfunc) (sigval_t); + sigval_t sival; +}; + + +/* Helper thread to call the user-provided function. */ +static void * +timer_sigev_thread (void *arg) +{ + /* The parent thread has all signals blocked. This is a bit + surprising for user code, although valid. We unblock all + signals. */ + sigset_t ss; + sigemptyset (&ss); + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, NULL, _NSIG / 8); + + struct thread_start_data *td = (struct thread_start_data *) arg; + + void (*thrfunc) (sigval_t) = td->thrfunc; + sigval_t sival = td->sival; + + /* The TD object was allocated in timer_helper_thread. */ + free (td); + + /* Call the user-provided function. */ + thrfunc (sival); + + return NULL; +} + + +/* Helper function to support starting threads for SIGEV_THREAD. */ +static void * +timer_helper_thread (void *arg) +{ + /* Wait for the SIGTIMER signal, allowing the setXid signal, and + none else. */ + sigset_t ss; + sigemptyset (&ss); + __sigaddset (&ss, SIGTIMER); + + /* Endless loop of waiting for signals. The loop is only ended when + the thread is canceled. */ + while (1) + { + siginfo_t si; + + /* sigwaitinfo cannot be used here, since it deletes + SIGCANCEL == SIGTIMER from the set. */ + + int oldtype = LIBC_CANCEL_ASYNC (); + + /* XXX The size argument hopefully will have to be changed to the + real size of the user-level sigset_t. */ + int result = INLINE_SYSCALL (rt_sigtimedwait, 4, &ss, &si, NULL, + _NSIG / 8); + + LIBC_CANCEL_RESET (oldtype); + + if (result > 0) + { + if (si.si_code == SI_TIMER) + { + struct timer *tk = (struct timer *) si.si_ptr; + + /* Check the timer is still used and will not go away + while we are reading the values here. */ + pthread_mutex_lock (&__active_timer_sigev_thread_lock); + + struct timer *runp = __active_timer_sigev_thread; + while (runp != NULL) + if (runp == tk) + break; + else + runp = runp->next; + + if (runp != NULL) + { + struct thread_start_data *td = malloc (sizeof (*td)); + + /* There is not much we can do if the allocation fails. */ + if (td != NULL) + { + /* This is the signal we are waiting for. */ + td->thrfunc = tk->thrfunc; + td->sival = tk->sival; + + pthread_t th; + (void) pthread_create (&th, &tk->attr, + timer_sigev_thread, td); + } + } + + pthread_mutex_unlock (&__active_timer_sigev_thread_lock); + } + else if (si.si_code == SI_TKILL) + /* The thread is canceled. */ + pthread_exit (NULL); + } + } +} + + +/* Control variable for helper thread creation. */ +pthread_once_t __helper_once attribute_hidden; + + +/* TID of the helper thread. */ +pid_t __helper_tid attribute_hidden; + + +/* Reset variables so that after a fork a new helper thread gets started. */ +static void +reset_helper_control (void) +{ + __helper_once = PTHREAD_ONCE_INIT; + __helper_tid = 0; +} + + +void +attribute_hidden +__start_helper_thread (void) +{ + /* The helper thread needs only very little resources + and should go away automatically when canceled. */ + pthread_attr_t attr; + (void) pthread_attr_init (&attr); + (void) pthread_attr_setstacksize (&attr, __pthread_get_minstack (&attr)); + + /* Block all signals in the helper thread but SIGSETXID. To do this + thoroughly we temporarily have to block all signals here. The + helper can lose wakeups if SIGCANCEL is not blocked throughout, + but sigfillset omits it SIGSETXID. So, we add SIGCANCEL back + explicitly here. */ + sigset_t ss; + sigset_t oss; + sigfillset (&ss); + __sigaddset (&ss, SIGCANCEL); + INTERNAL_SYSCALL_DECL (err); + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &ss, &oss, _NSIG / 8); + + /* Create the helper thread for this timer. */ + pthread_t th; + int res = pthread_create (&th, &attr, timer_helper_thread, NULL); + if (res == 0) + /* We managed to start the helper thread. */ + __helper_tid = ((struct pthread *) th)->tid; + + /* Restore the signal mask. */ + INTERNAL_SYSCALL (rt_sigprocmask, err, 4, SIG_SETMASK, &oss, NULL, + _NSIG / 8); + + /* No need for the attribute anymore. */ + (void) pthread_attr_destroy (&attr); + + /* We have to make sure that after fork()ing a new helper thread can + be created. */ + pthread_atfork (NULL, NULL, reset_helper_control); +} diff --git a/sysdeps/unix/sysv/linux/timer_settime.c b/sysdeps/unix/sysv/linux/timer_settime.c new file mode 100644 index 0000000000..f7f7c91c51 --- /dev/null +++ b/sysdeps/unix/sysv/linux/timer_settime.c @@ -0,0 +1,46 @@ +/* Copyright (C) 2003-2014 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper , 2003. + + 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, see . */ + +#include +#include +#include +#include +#include "kernel-posix-timers.h" + + +#ifdef timer_settime_alias +# define timer_settime timer_settime_alias +#endif + + +int +timer_settime (timerid, flags, value, ovalue) + timer_t timerid; + int flags; + const struct itimerspec *value; + struct itimerspec *ovalue; +{ +#undef timer_settime + struct timer *kt = (struct timer *) timerid; + + /* Delete the kernel timer object. */ + int res = INLINE_SYSCALL (timer_settime, 4, kt->ktimerid, flags, + value, ovalue); + + return res; +} diff --git a/sysdeps/unix/sysv/linux/tst-setgetname.c b/sysdeps/unix/sysv/linux/tst-setgetname.c new file mode 100644 index 0000000000..f5693e26c4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-setgetname.c @@ -0,0 +1,315 @@ +/* Test pthread_setname_np and pthread_getname_np. + Copyright (C) 2013-2014 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, see . */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* New name of process. */ +#define NEW_NAME "setname" + +/* Name of process which is one byte too big + e.g. 17 bytes including null-terminator */ +#define BIG_NAME "....V....X....XV" + +/* Longest name of a process + e.g. 16 bytes including null-terminator. */ +#define LONGEST_NAME "....V....X....X" + +/* One less than longest name with unique + characters to detect modification. */ +#define CANARY_NAME "abcdefghijklmn" + +/* On Linux the maximum length of the name of a task *including* the null + terminator. */ +#define TASK_COMM_LEN 16 + +long +gettid (void) +{ + return syscall(__NR_gettid); +} + +/* On Linux we can read this task's name from /proc. */ +int +get_self_comm (long tid, char *buf, size_t len) +{ + int res = 0; +#define FMT "/proc/self/task/%lu/comm" + char fname[sizeof (FMT) + 8]; + sprintf (fname, FMT, (unsigned long) tid); + + int fd = open (fname, O_RDONLY); + if (fd == -1) + return errno; + + ssize_t n = read (fd, (void *) buf, len); + if (n < 0) + res = errno; + else + { + if (buf[n - 1] == '\n') + buf[n - 1] = '\0'; + else if (n == len) + res = ERANGE; + else + buf[n] = '\0'; + } + + close (fd); + return res; +} + +int +do_test (int argc, char **argv) +{ + pthread_t self; + int res; + int ret = 0; + char name[TASK_COMM_LEN]; + char name_check[TASK_COMM_LEN]; + + memset (name, '\0', TASK_COMM_LEN); + memset (name_check, '\0', TASK_COMM_LEN); + + /* Test 1: Get the name of the task via pthread_getname_np and /proc + and verify that they both match. */ + self = pthread_self (); + res = pthread_getname_np (self, name, TASK_COMM_LEN); + + if (res == 0) + { + res = get_self_comm (gettid (), name_check, TASK_COMM_LEN); + +#if !__ASSUME_PROC_PID_TASK_COMM + /* On this first test we look for ENOENT to be returned from + get_self_comm to indicate that the kernel is older than + 2.6.33 and doesn't contain comm within the proc structure. + In that case we skip the entire test. */ + if (res == ENOENT) + { + printf ("SKIP: The kernel does not have /proc/self/task/%%lu/comm.\n"); + return 0; + } +#endif + + if (res == 0) + { + if (strncmp (name, name_check, strlen (BIG_NAME)) == 0) + printf ("PASS: Test 1 - pthread_getname_np and /proc agree.\n"); + else + { + printf ("FAIL: Test 1 - pthread_getname_np and /proc differ" + " i.e. %s != %s\n", name, name_check); + ret++; + } + } + else + { + printf ("FAIL: Test 1 - unable read task name via proc.\n"); + ret++; + } + } + else + { + printf ("FAIL: Test 1 - pthread_getname_np failed with error %d\n", res); + ret++; + } + + /* Test 2: Test setting the name and then independently verify it + was set. */ + res = pthread_setname_np (self, NEW_NAME); + + if (res == 0) + { + res = get_self_comm (gettid (), name_check, TASK_COMM_LEN); + if (res == 0) + { + if (strncmp (NEW_NAME, name_check, strlen (BIG_NAME)) == 0) + printf ("PASS: Test 2 - Value used in pthread_setname_np and" + " /proc agree.\n"); + else + { + printf ("FAIL: Test 2 - Value used in pthread_setname_np" + " and /proc differ i.e. %s != %s\n", + NEW_NAME, name_check); + ret++; + } + } + else + { + printf ("FAIL: Test 2 - unable to read task name via proc.\n"); + ret++; + } + } + else + { + printf ("FAIL: Test 2 - pthread_setname_np failed with error %d\n", res); + ret++; + } + + /* Test 3: Test setting a name that is one-byte too big. */ + res = pthread_getname_np (self, name, TASK_COMM_LEN); + + if (res == 0) + { + res = pthread_setname_np (self, BIG_NAME); + if (res != 0) + { + if (res == ERANGE) + { + printf ("PASS: Test 3 - pthread_setname_np returned ERANGE" + " for a process name that was too long.\n"); + + /* Verify the old name didn't change. */ + res = get_self_comm (gettid (), name_check, TASK_COMM_LEN); + if (res == 0) + { + if (strncmp (name, name_check, strlen (BIG_NAME)) == 0) + printf ("PASS: Test 3 - Original name unchanged after" + " pthread_setname_np returned ERANGE.\n"); + else + { + printf ("FAIL: Test 3 - Original name changed after" + " pthread_setname_np returned ERANGE" + " i.e. %s != %s\n", + name, name_check); + ret++; + } + } + else + { + printf ("FAIL: Test 3 - unable to read task name.\n"); + ret++; + } + } + else + { + printf ("FAIL: Test 3 - Wrong error returned" + " i.e. ERANGE != %d\n", res); + ret++; + } + } + else + { + printf ("FAIL: Test 3 - Too-long name accepted by" + " pthread_setname_np.\n"); + ret++; + } + } + else + { + printf ("FAIL: Test 3 - Unable to get original name.\n"); + ret++; + } + + /* Test 4: Verify that setting the longest name works. */ + res = pthread_setname_np (self, LONGEST_NAME); + + if (res == 0) + { + res = get_self_comm (gettid (), name_check, TASK_COMM_LEN); + if (res == 0) + { + if (strncmp (LONGEST_NAME, name_check, strlen (BIG_NAME)) == 0) + printf ("PASS: Test 4 - Longest name set via pthread_setname_np" + " agrees with /proc.\n"); + else + { + printf ("FAIL: Test 4 - Value used in pthread_setname_np and /proc" + " differ i.e. %s != %s\n", LONGEST_NAME, name_check); + ret++; + } + } + else + { + printf ("FAIL: Test 4 - unable to read task name via proc.\n"); + ret++; + } + } + else + { + printf ("FAIL: Test 4 - pthread_setname_np failed with error %d\n", res); + ret++; + } + + /* Test 5: Verify that getting a long name into a small buffer fails. */ + strncpy (name, CANARY_NAME, strlen (CANARY_NAME) + 1); + + /* Claim the buffer length is strlen (LONGEST_NAME). This is one character + too small to hold LONGEST_NAME *and* the null terminator. We should get + back ERANGE and name should be unmodified. */ + res = pthread_getname_np (self, name, strlen (LONGEST_NAME)); + + if (res != 0) + { + if (res == ERANGE) + { + if (strncmp (CANARY_NAME, name, strlen (BIG_NAME)) == 0) + { + printf ("PASS: Test 5 - ERANGE and buffer unmodified.\n"); + } + else + { + printf ("FAIL: Test 5 - Original buffer modified.\n"); + ret++; + } + } + else + { + printf ("FAIL: Test 5 - Did not return ERANGE for small buffer.\n"); + ret++; + } + } + else + { + printf ("FAIL: Test 5 - Returned name longer than buffer.\n"); + ret++; + } + + /* Test 6: Lastly make sure we can read back the longest name. */ + res = pthread_getname_np (self, name, strlen (LONGEST_NAME) + 1); + + if (res == 0) + { + if (strncmp (LONGEST_NAME, name, strlen (BIG_NAME)) == 0) + { + printf ("PASS: Test 6 - Read back longest name correctly.\n"); + } + else + { + printf ("FAIL: Test 6 - Read \"%s\" instead of longest name.\n", + name); + ret++; + } + } + else + { + printf ("FAIL: Test 6 - pthread_getname_np failed with error %d\n", res); + ret++; + } + + return ret; +} + +#include diff --git a/sysdeps/unix/sysv/linux/x86/pthread_mutex_cond_lock.c b/sysdeps/unix/sysv/linux/x86/pthread_mutex_cond_lock.c index 34c705235a..8d215915df 100644 --- a/sysdeps/unix/sysv/linux/x86/pthread_mutex_cond_lock.c +++ b/sysdeps/unix/sysv/linux/x86/pthread_mutex_cond_lock.c @@ -19,4 +19,4 @@ already elided locks. */ #include -#include "sysdeps/unix/sysv/linux/pthread_mutex_cond_lock.c" +#include diff --git a/sysdeps/unix/sysv/linux/x86_64/sigaction.c b/sysdeps/unix/sysv/linux/x86_64/sigaction.c index 6735b70c10..53a8134b6a 100644 --- a/sysdeps/unix/sysv/linux/x86_64/sigaction.c +++ b/sysdeps/unix/sysv/linux/x86_64/sigaction.c @@ -73,15 +73,8 @@ __libc_sigaction (int sig, const struct sigaction *act, struct sigaction *oact) } libc_hidden_def (__libc_sigaction) -#ifdef WRAPPER_INCLUDE -# include WRAPPER_INCLUDE -#endif - -#ifndef LIBC_SIGACTION -weak_alias (__libc_sigaction, __sigaction) -libc_hidden_weak (__sigaction) -weak_alias (__libc_sigaction, sigaction) -#endif +#include + /* NOTE: Please think twice before making any changes to the bits of code below. GDB needs some intimate knowledge about it to -- cgit v1.2.1