From 32c075e1f01849e161724bbd400ba77244e482cc Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 31 Jul 2007 13:33:18 +0000 Subject: . --- nptl/ChangeLog | 253 ++++++++++++--------- nptl/Makefile | 10 +- nptl/allocatestack.c | 59 ++++- nptl/descr.h | 3 +- nptl/init.c | 6 +- nptl/pthreadP.h | 4 +- nptl/pthread_attr_setstack.c | 15 +- nptl/pthread_attr_setstacksize.c | 14 +- nptl/pthread_barrier_wait.c | 77 ------- nptl/pthread_cond_broadcast.c | 86 ------- nptl/pthread_cond_signal.c | 61 ----- nptl/pthread_cond_timedwait.c | 214 ----------------- nptl/pthread_cond_wait.c | 191 ---------------- nptl/pthread_getattr_np.c | 10 +- nptl/pthread_getcpuclockid.c | 57 ----- nptl/pthread_mutex_lock.c | 4 +- nptl/pthread_mutex_timedlock.c | 8 +- nptl/pthread_mutex_trylock.c | 8 +- nptl/pthread_once.c | 54 ----- nptl/pthread_rwlock_rdlock.c | 95 -------- nptl/pthread_rwlock_timedrdlock.c | 137 ----------- nptl/pthread_rwlock_timedwrlock.c | 127 ----------- nptl/pthread_rwlock_unlock.c | 57 ----- nptl/pthread_rwlock_wrlock.c | 87 ------- nptl/pthread_spin_destroy.c | 29 --- nptl/pthread_spin_init.c | 28 --- nptl/pthread_spin_unlock.c | 30 --- nptl/sysdeps/alpha/tls.h | 28 ++- nptl/sysdeps/i386/tls.h | 26 ++- nptl/sysdeps/ia64/pthread_spin_unlock.c | 4 +- nptl/sysdeps/ia64/tls.h | 28 ++- nptl/sysdeps/powerpc/tls.h | 28 ++- nptl/sysdeps/pthread/pthread_barrier_wait.c | 77 +++++++ nptl/sysdeps/pthread/pthread_cond_broadcast.c | 86 +++++++ nptl/sysdeps/pthread/pthread_cond_signal.c | 61 +++++ nptl/sysdeps/pthread/pthread_cond_timedwait.c | 214 +++++++++++++++++ nptl/sysdeps/pthread/pthread_cond_wait.c | 191 ++++++++++++++++ nptl/sysdeps/pthread/pthread_getcpuclockid.c | 57 +++++ nptl/sysdeps/pthread/pthread_once.c | 54 +++++ nptl/sysdeps/pthread/pthread_rwlock_rdlock.c | 95 ++++++++ nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c | 137 +++++++++++ nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c | 127 +++++++++++ nptl/sysdeps/pthread/pthread_rwlock_unlock.c | 57 +++++ nptl/sysdeps/pthread/pthread_rwlock_wrlock.c | 87 +++++++ nptl/sysdeps/pthread/pthread_spin_destroy.c | 29 +++ nptl/sysdeps/pthread/pthread_spin_init.c | 28 +++ nptl/sysdeps/pthread/pthread_spin_unlock.c | 30 +++ nptl/sysdeps/s390/tls.h | 29 ++- nptl/sysdeps/sh/tls.h | 28 ++- nptl/sysdeps/sparc/tls.h | 34 ++- .../sysdeps/unix/sysv/linux/alpha/bits/local_lim.h | 3 - .../sysdeps/unix/sysv/linux/alpha/bits/semaphore.h | 3 + nptl/sysdeps/unix/sysv/linux/bits/local_lim.h | 3 - nptl/sysdeps/unix/sysv/linux/fork.c | 9 +- nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h | 3 + .../unix/sysv/linux/i386/i486/sem_timedwait.S | 11 +- nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h | 10 - nptl/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h | 3 - nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h | 3 + nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c | 22 +- nptl/sysdeps/unix/sysv/linux/powerpc/Versions | 4 - .../unix/sysv/linux/powerpc/bits/local_lim.h | 93 -------- .../unix/sysv/linux/powerpc/bits/semaphore.h | 3 + .../sysv/linux/powerpc/pthread_attr_setstack.c | 2 - .../sysv/linux/powerpc/pthread_attr_setstacksize.c | 8 - nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h | 2 +- nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h | 3 + .../unix/sysv/linux/s390/s390-32/sysdep-cancel.h | 21 +- .../unix/sysv/linux/s390/s390-64/sysdep-cancel.h | 21 +- nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h | 3 + .../sysdeps/unix/sysv/linux/sparc/bits/local_lim.h | 3 - .../sysdeps/unix/sysv/linux/sparc/bits/semaphore.h | 3 + .../sparc/sparc32/sparcv9/pthread_barrier_wait.c | 2 +- .../unix/sysv/linux/x86_64/bits/semaphore.h | 3 + nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S | 4 +- nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h | 28 +-- .../sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S | 10 +- nptl/sysdeps/x86_64/tls.h | 26 ++- nptl/tst-cancel-wrappers.sh | 3 +- nptl/tst-cancel4.c | 44 +++- nptl/tst-robust9.c | 94 ++++++++ nptl/tst-robustpi9.c | 2 + nptl/tst-sem10.c | 88 +++++++ nptl/tst-tls5.h | 2 +- 84 files changed, 2098 insertions(+), 1703 deletions(-) delete mode 100644 nptl/pthread_barrier_wait.c delete mode 100644 nptl/pthread_cond_broadcast.c delete mode 100644 nptl/pthread_cond_signal.c delete mode 100644 nptl/pthread_cond_timedwait.c delete mode 100644 nptl/pthread_cond_wait.c delete mode 100644 nptl/pthread_getcpuclockid.c delete mode 100644 nptl/pthread_once.c delete mode 100644 nptl/pthread_rwlock_rdlock.c delete mode 100644 nptl/pthread_rwlock_timedrdlock.c delete mode 100644 nptl/pthread_rwlock_timedwrlock.c delete mode 100644 nptl/pthread_rwlock_unlock.c delete mode 100644 nptl/pthread_rwlock_wrlock.c delete mode 100644 nptl/pthread_spin_destroy.c delete mode 100644 nptl/pthread_spin_init.c delete mode 100644 nptl/pthread_spin_unlock.c create mode 100644 nptl/sysdeps/pthread/pthread_barrier_wait.c create mode 100644 nptl/sysdeps/pthread/pthread_cond_broadcast.c create mode 100644 nptl/sysdeps/pthread/pthread_cond_signal.c create mode 100644 nptl/sysdeps/pthread/pthread_cond_timedwait.c create mode 100644 nptl/sysdeps/pthread/pthread_cond_wait.c create mode 100644 nptl/sysdeps/pthread/pthread_getcpuclockid.c create mode 100644 nptl/sysdeps/pthread/pthread_once.c create mode 100644 nptl/sysdeps/pthread/pthread_rwlock_rdlock.c create mode 100644 nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c create mode 100644 nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c create mode 100644 nptl/sysdeps/pthread/pthread_rwlock_unlock.c create mode 100644 nptl/sysdeps/pthread/pthread_rwlock_wrlock.c create mode 100644 nptl/sysdeps/pthread/pthread_spin_destroy.c create mode 100644 nptl/sysdeps/pthread/pthread_spin_init.c create mode 100644 nptl/sysdeps/pthread/pthread_spin_unlock.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h delete mode 100644 nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c delete mode 100644 nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c create mode 100644 nptl/tst-robust9.c create mode 100644 nptl/tst-robustpi9.c create mode 100644 nptl/tst-sem10.c (limited to 'nptl') diff --git a/nptl/ChangeLog b/nptl/ChangeLog index 0b1d6300ac..47ea82ff5d 100644 --- a/nptl/ChangeLog +++ b/nptl/ChangeLog @@ -1,41 +1,107 @@ -2007-01-10 Ulrich Drepper +2007-07-27 Jakub Jelinek - * sysdeps/unix/sysv/linux/x86_64/lowlevellock.h: Cleanups. Define - FUTEX_CMP_REQUEUE and lll_futex_requeue. + * sysdeps/sparc/tls.h (tcbhead_t): Move gscope_flag to the end + of the structure for sparc32. -2006-12-28 David S. Miller +2007-07-26 Aurelien Jarno - * shlib-versions: Fix sparc64 linux target specification. + * sysdeps/sparc/tls.h (tcbhead_t): Add gscope_flag. -2007-01-10 Jakub Jelinek +2007-06-22 Jakub Jelinek - * sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c: - Adjust include path for pthread_barrier_wait.c move. + * pthread_getattr_np.c (pthread_getattr_np): Clear cpuset and + cpusetsize if pthread_getaffinity_np failed with ENOSYS. -2006-12-21 Jakub Jelinek +2007-05-28 Jakub Jelinek - * sysdeps/unix/sysv/linux/pthread_kill.c (pthread_kill): Make sure - tid isn't reread from pd->tid in between ESRCH test and the syscall. + * sysdeps/i386/tls.h (THREAD_GSCOPE_RESET_FLAG): Use explicit + insn suffix. + (THREAD_GSCOPE_GET_FLAG): Remove. + * sysdeps/x86_64/tls.h (THREAD_GSCOPE_GET_FLAG): Remove. + * allocatestack.c (__wait_lookup_done): Revert 2007-05-24 + changes. + * sysdeps/powerpc/tls.h (tcbhead_t): Remove gscope_flag. + (THREAD_GSCOPE_GET_FLAG): Remove. + (THREAD_GSCOPE_RESET_FLAG): Use THREAD_SELF->header.gscope_flag + instead of THREAD_GSCOPE_GET_FLAG. + (THREAD_GSCOPE_SET_FLAG): Likewise. Add atomic_write_barrier after + it. + * sysdeps/s390/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + * sysdeps/sparc/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + * sysdeps/sh/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + * sysdeps/ia64/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + +2007-05-24 Richard Henderson + + * descr.h (struct pthread): Add header.gscope_flag. + * sysdeps/alpha/tls.h (THREAD_GSCOPE_FLAG_UNUSED, + THREAD_GSCOPE_FLAG_USED, THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_WAIT): Define. + +2007-05-26 Ulrich Drepper + + * allocatestack.c: Revert last change. + * init.c: Likewise. + * sysdeps/i386/tls.h: Likewise. + * sysdeps/x86_64/tls.h: Likewise. + +2007-05-24 Jakub Jelinek -2006-12-06 Jakub Jelinek + * sysdeps/powerpc/tls.h (tcbhead_t): Add gscope_flag. + (THREAD_GSCOPE_FLAG_UNUSED, THREAD_GSCOPE_FLAG_USED, + THREAD_GSCOPE_FLAG_WAIT): Define. + (THREAD_GSCOPE_GET_FLAG, THREAD_GSCOPE_SET_FLAG, + THREAD_GSCOPE_RESET_FLAG, THREAD_GSCOPE_WAIT): Define. + * sysdeps/i386/tls.h (THREAD_GSCOPE_WAIT): Don't use + PTR_DEMANGLE. + (THREAD_GSCOPE_GET_FLAG): Define. + * sysdeps/x86_64/tls.h (THREAD_GSCOPE_GET_FLAG): Define. + * allocatestack.c (__wait_lookup_done): Use THREAD_GSCOPE_GET_FLAG + instead of ->header.gscope_flag directly. - * sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h (PSEUDO): Handle - 6 argument cancellable syscalls. - (STM_6, LM_6, LR7_0, LR7_1, LR7_2, LR7_3, LR7_4, LR7_5, LR7_6): Define. - * sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h (PSEUDO): Handle - 6 argument cancellable syscalls. - (STM_6, LM_6, LR7_0, LR7_1, LR7_2, LR7_3, LR7_4, LR7_5, LR7_6): Define. +2007-05-21 Ulrich Drepper + + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Remove ptr_wait_lookup_done again. + * init.c (pthread_functions): Don't add .ptr_wait_lookup_done here. + (__pthread_initialize_minimal_internal): Initialize + _dl_wait_lookup_done pointer in _rtld_global directly. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Remove code to code _dl_wait_lookup_done. + * sysdeps/x86_64/tls.h (THREAD_GSCOPE_WAIT): The pointer is not + encrypted for now. + +2007-05-19 Ulrich Drepper + + * allocatestack.c (__wait_lookup_done): New function. + * sysdeps/pthread/pthread-functions.h (struct pthread_functions): + Add ptr_wait_lookup_done. + * init.c (pthread_functions): Initialize .ptr_wait_lookup_done. + * pthreadP.h: Declare __wait_lookup_done. + * sysdeps/i386/tls.h (tcbhead_t): Add gscope_flag. + Define macros to implement reference handling of global scope. + * sysdeps/x86_64/tls.h: Likewise. + * sysdeps/unix/sysv/linux/libc_pthread_init.c (__libc_pthread_init): + Initialize GL(dl_wait_lookup_done). 2006-12-09 Ulrich Drepper * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_mrlock_initialize): Add missing closing parenthesis. -2006-10-30 Jakub Jelinek - - * sysdeps/ia64/pthread_spin_unlock.c (pthread_spin_unlock): Use - __sync_lock_release instead of __sync_lock_release_si. - 2006-10-29 Jakub Jelinek * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h (RTLD_SINGLE_THREAD_P): @@ -52,50 +118,6 @@ * sysdeps/unix/sysv/linux/sparc/sparc64/sysdep-cancel.h: Likewise. * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h: Likewise. -2006-10-27 Ulrich Drepper - - * sysdeps/pthread/pthread_barrier_wait.c: Move to... - * pthread_barrier_wait.c: ...here. - * sysdeps/pthread/pthread_cond_broadcast.c: Move to... - * pthread_cond_broadcast.c: ...here. - * sysdeps/pthread/pthread_cond_signal.c: Move to... - * pthread_cond_signal.c: ...here. - * sysdeps/pthread/pthread_cond_timedwait.c: Move to... - * pthread_cond_timedwait.c: ...here. - * sysdeps/pthread/pthread_cond_wait.c: Move to... - * pthread_cond_wait.c: ...here. - * sysdeps/pthread/pthread_once.c: Move to... - * pthread_once.c: ...here. - * sysdeps/pthread/pthread_rwlock_rdlock.c: Move to... - * pthread_rwlock_rdlock.c: ...here. - * sysdeps/pthread/pthread_rwlock_timedrdlock.c: Move to... - * pthread_rwlock_timedrdlock.c: ...here. - * sysdeps/pthread/pthread_rwlock_timedwrlock.c: Move to... - * pthread_rwlock_timedwrlock.c: ...here. - * sysdeps/pthread/pthread_rwlock_unlock.c: Move to... - * pthread_rwlock_unlock.c: ...here. - * sysdeps/pthread/pthread_rwlock_wrlock.c: Move to... - * pthread_rwlock_wrlock.c: ...here. - * sysdeps/pthread/pthread_spin_destroy.c: Move to... - * pthread_spin_destroy.c: ...here. - * sysdeps/pthread/pthread_spin_init.c: Move to... - * pthread_spin_init.c: ...here. - * sysdeps/pthread/pthread_spin_unlock.c: Move to... - * pthread_spin_unlock.c: ...here. - * sysdeps/pthread/pthread_getcpuclockid.c: Move to... - * pthread_getcpuclockid.c: ...here. - - * init.c: USE_TLS support is now always enabled. - * tst-tls5.h: Likewise. - * sysdeps/alpha/tls.h: Likewise. - * sysdeps/i386/tls.h: Likewise. - * sysdeps/ia64/tls.h: Likewise. - * sysdeps/powerpc/tls.h: Likewise. - * sysdeps/s390/tls.h: Likewise. - * sysdeps/sh/tls.h: Likewise. - * sysdeps/sparc/tls.h: Likewise. - * sysdeps/x86_64/tls.h: Likewise. - 2006-10-27 Jakub Jelinek * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_mrlock_lock, @@ -125,59 +147,74 @@ * sysdeps/unix/sysv/linux/sh/sysdep-cancel.h (SINGLE_THREAD_P): Likewise. -2006-10-26 Jakub Jelinek +2006-10-09 Ulrich Drepper - * pthread_attr_setstacksize.c (NEW_VERNUM): Define to GLIBC_2_3_3 - by default rather than 2_3_3. + * sysdeps/unix/sysv/linux/rtld-lowlevel.h: New file.. -2006-10-17 Jakub Jelinek +2007-05-25 Ulrich Drepper - * sysdeps/unix/sysv/linux/rtld-lowlevel.h (__rtld_mrlock_lock, - __rtld_mrlock_unlock, __rtld_mrlock_change, __rtld_mrlock_done): Use - atomic_* instead of catomic_* macros. + * Makefile (tests): Add tst-sem10. + * tst-sem10.c: New file. -2006-10-12 Ulrich Drepper +2007-05-25 Ulrich Drepper + Jakub Jelinek - [BZ #3285] - * sysdeps/unix/sysv/linux/bits/local_lim.h: Add SEM_VALUE_MAX. - * sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h: Likewise. - * sysdeps/unix/sysv/linux/sparc/bits/local_lim.h: Likewise. - * sysdeps/unix/sysv/linux/alpha/bits/local_lim.h: Likewise. - * sysdeps/unix/sysv/linux/ia64/bits/local_lim.h: Likewise. - * sysdeps/unix/sysv/linux/i386/bits/semaphore.h: Remove SEM_VALUE_MAX. - * sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h: Likewise. - * sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h: Likewise. - * sysdeps/unix/sysv/linux/sparc/bits/semaphore.h: Likewise. - * sysdeps/unix/sysv/linux/alpha/bits/semaphore.h: Likewise. - * sysdeps/unix/sysv/linux/sh/bits/semaphore.h: Likewise. - * sysdeps/unix/sysv/linux/ia64/bits/semaphore.h: Likewise. - * sysdeps/unix/sysv/linux/s390/bits/semaphore.h: Likewise. + * sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S (sem_timedwait): + Move __pthread_enable_asynccancel right before futex syscall. + * sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S (sem_timedwait): + Likewise. -2006-10-11 Ulrich Drepper +2007-05-21 Jakub Jelinek - * sysdeps/unix/sysv/linux/i386/sysdep-cancel.h: Add support for - cancelable syscalls with six parameters. + * tst-robust9.c (do_test): Don't fail if ENABLE_PI and + pthread_mutex_init failed with ENOTSUP. - * sysdeps/unix/sysv/linux/rtld-lowlevel.h: Use catomic_* - operations instead of atomic_*. +2007-05-17 Ulrich Drepper -2006-10-09 Ulrich Drepper + [BZ #4512] + * pthread_mutex_lock.c: Preserve FUTEX_WAITERS bit when dead owner + is detected. + * pthread_mutex_timedlock.c: Likewise. + * pthread_mutex_trylock.c: Likewise. + Patch in part by Atsushi Nemoto . - * sysdeps/unix/sysv/linux/rtld-lowlevel.h: New file.. + * Makefile (tests): Add tst-robust9 and tst-robustpi9. + * tst-robust9.c: New file. + * tst-robustpi9.c: New file. -2006-10-07 Ulrich Drepper +2007-05-07 Ulrich Drepper - * sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h: New file. - * sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c: New file. - * sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c: - New file. - * pthread_attr_setstack.c: Allow overwriting the version number of the - new symbol. - * pthread_attr_setstacksize.c: Likewise. - (__old_pthread_attr_setstacksize): If STACKSIZE_ADJUST is defined use - it. - * sysdeps/unix/sysv/linux/powerpc/Versions (libpthread): Add - pthread_attr_setstack and pthread_attr_setstacksize to GLIBC_2.6. + * sysdeps/unix/sysv/linux/lowlevelrobustlock.c + (__lll_robust_lock_wait): Fix race caused by reloading of futex value. + (__lll_robust_timedlock_wait): Likewise. + Reported by Alexey Kuznetsov . + +2007-05-06 Mike Frysinger + + [BZ #4465] + * tst-cancel-wrappers.sh: Set C["fdatasync"] to 1. + * tst-cancel4.c (tf_fdatasync): New test. + +2007-02-25 Ulrich Drepper + + * sysdeps/unix/sysv/linux/fork.c (__libc_fork): Reset refcntr in + new thread, don't just decrement it. + Patch by Suzuki K P . + +2007-02-09 Jakub Jelinek + + * sysdeps/unix/sysv/linux/x86_64/lowlevellock.S + (__lll_mutex_timedlock_wait): Use correct pointer when we don't + call into the kernel to delay. + +2006-12-28 David S. Miller + + * shlib-versions: Fix sparc64 linux target specification. + +2006-12-21 Jakub Jelinek + + * sysdeps/unix/sysv/linux/pthread_kill.c (pthread_kill): Make sure + tid isn't reread from pd->tid in between ESRCH test and the syscall. 2006-09-24 Ulrich Drepper diff --git a/nptl/Makefile b/nptl/Makefile index 9393cab009..61cd25756c 100644 --- a/nptl/Makefile +++ b/nptl/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 2002,2003,2004,2005,2006 Free Software Foundation, Inc. +# Copyright (C) 2002,2003,2004,2005,2006,2007 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 @@ -209,16 +209,16 @@ tests = tst-typesizes \ tst-cond14 tst-cond15 tst-cond16 tst-cond17 tst-cond18 tst-cond19 \ tst-cond20 tst-cond21 tst-cond22 \ tst-robust1 tst-robust2 tst-robust3 tst-robust4 tst-robust5 \ - tst-robust6 tst-robust7 tst-robust8 \ - tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 \ - tst-robustpi5 tst-robustpi6 tst-robustpi7 tst-robustpi8 \ + tst-robust6 tst-robust7 tst-robust8 tst-robust9 \ + tst-robustpi1 tst-robustpi2 tst-robustpi3 tst-robustpi4 tst-robustpi5 \ + tst-robustpi6 tst-robustpi7 tst-robustpi8 tst-robustpi9 \ tst-rwlock1 tst-rwlock2 tst-rwlock3 tst-rwlock4 tst-rwlock5 \ tst-rwlock6 tst-rwlock7 tst-rwlock8 tst-rwlock9 tst-rwlock10 \ tst-rwlock11 tst-rwlock12 tst-rwlock13 tst-rwlock14 \ tst-once1 tst-once2 tst-once3 tst-once4 \ tst-key1 tst-key2 tst-key3 tst-key4 \ tst-sem1 tst-sem2 tst-sem3 tst-sem4 tst-sem5 tst-sem6 tst-sem7 \ - tst-sem8 tst-sem9 \ + tst-sem8 tst-sem9 tst-sem10 \ tst-barrier1 tst-barrier2 tst-barrier3 tst-barrier4 \ tst-align tst-align2 tst-align3 \ tst-basic1 tst-basic2 tst-basic3 tst-basic4 tst-basic5 tst-basic6 \ diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c index c05cd47dff..736c63d69f 100644 --- a/nptl/allocatestack.c +++ b/nptl/allocatestack.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -982,3 +982,60 @@ __pthread_init_static_tls (struct link_map *map) lll_unlock (stack_cache_lock); } + + +void +attribute_hidden +__wait_lookup_done (void) +{ + lll_lock (stack_cache_lock); + + struct pthread *self = THREAD_SELF; + + /* Iterate over the list with system-allocated threads first. */ + list_t *runp; + list_for_each (runp, &stack_used) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self || t->header.gscope_flag == THREAD_GSCOPE_FLAG_UNUSED) + continue; + + int *const gscope_flagp = &t->header.gscope_flag; + + /* We have to wait until this thread is done with the global + scope. First tell the thread that we are waiting and + possibly have to be woken. */ + if (atomic_compare_and_exchange_bool_acq (gscope_flagp, + THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_FLAG_USED)) + continue; + + do + lll_futex_wait (gscope_flagp, THREAD_GSCOPE_FLAG_WAIT); + while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT); + } + + /* Now the list with threads using user-allocated stacks. */ + list_for_each (runp, &__stack_user) + { + struct pthread *t = list_entry (runp, struct pthread, list); + if (t == self || t->header.gscope_flag == THREAD_GSCOPE_FLAG_UNUSED) + continue; + + int *const gscope_flagp = &t->header.gscope_flag; + + /* We have to wait until this thread is done with the global + scope. First tell the thread that we are waiting and + possibly have to be woken. */ + if (atomic_compare_and_exchange_bool_acq (gscope_flagp, + THREAD_GSCOPE_FLAG_WAIT, + THREAD_GSCOPE_FLAG_USED)) + continue; + + do + lll_futex_wait (gscope_flagp, THREAD_GSCOPE_FLAG_WAIT); + while (*gscope_flagp == THREAD_GSCOPE_FLAG_WAIT); + } + + lll_unlock (stack_cache_lock); +} diff --git a/nptl/descr.h b/nptl/descr.h index 321ce85085..241ba527ed 100644 --- a/nptl/descr.h +++ b/nptl/descr.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -131,6 +131,7 @@ struct pthread struct { int multiple_threads; + int gscope_flag; } header; #endif diff --git a/nptl/init.c b/nptl/init.c index dddc975a5e..7144abd3fb 100644 --- a/nptl/init.c +++ b/nptl/init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -73,7 +73,7 @@ int __set_robust_list_avail; static const char nptl_version[] __attribute_used__ = VERSION; -#ifndef SHARED +#if defined USE_TLS && !defined SHARED extern void __libc_setup_tls (size_t tcbsize, size_t tcbalign); #endif @@ -386,6 +386,8 @@ __pthread_initialize_minimal_internal (void) GL(dl_init_static_tls) = &__pthread_init_static_tls; + GL(dl_wait_lookup_done) = &__wait_lookup_done; + /* Register the fork generation counter with the libc. */ #ifndef TLS_MULTIPLE_THREADS_IN_TCB __libc_multiple_threads_ptr = diff --git a/nptl/pthreadP.h b/nptl/pthreadP.h index f9634ab0ff..21ce6fe0b7 100644 --- a/nptl/pthreadP.h +++ b/nptl/pthreadP.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -545,6 +545,8 @@ extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden; extern void __free_stack_cache (void) attribute_hidden; +extern void __wait_lookup_done (void) attribute_hidden; + #ifdef SHARED # define PTHREAD_STATIC_FN_REQUIRE(name) #else diff --git a/nptl/pthread_attr_setstack.c b/nptl/pthread_attr_setstack.c index be79e32082..622e4a2250 100644 --- a/nptl/pthread_attr_setstack.c +++ b/nptl/pthread_attr_setstack.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -23,11 +23,6 @@ #include "pthreadP.h" -#ifndef NEW_VERNUM -# define NEW_VERNUM GLIBC_2_3_3 -#endif - - int __pthread_attr_setstack (attr, stackaddr, stacksize) pthread_attr_t *attr; @@ -59,9 +54,9 @@ strong_alias (__pthread_attr_setstack, pthread_attr_setstack) #else # include versioned_symbol (libpthread, __pthread_attr_setstack, pthread_attr_setstack, - NEW_VERNUM); + GLIBC_2_3_3); -# if SHLIB_COMPAT(libpthread, GLIBC_2_2, NEW_VERNUM) +# if SHLIB_COMPAT(libpthread, GLIBC_2_2, GLIBC_2_3_3) int __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, @@ -76,9 +71,9 @@ __old_pthread_attr_setstack (pthread_attr_t *attr, void *stackaddr, if (stacksize < 16384) return EINVAL; -# ifdef EXTRA_PARAM_CHECKS +# ifdef EXTRA_PARAM_CHECKS EXTRA_PARAM_CHECKS; -# endif +# endif iattr->stacksize = stacksize; iattr->stackaddr = (char *) stackaddr + stacksize; diff --git a/nptl/pthread_attr_setstacksize.c b/nptl/pthread_attr_setstacksize.c index 0974538986..f84a9f68e3 100644 --- a/nptl/pthread_attr_setstacksize.c +++ b/nptl/pthread_attr_setstacksize.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -22,10 +22,6 @@ #include #include "pthreadP.h" -#ifndef NEW_VERNUM -# define NEW_VERNUM GLIBC_2_3_3 -#endif - int __pthread_attr_setstacksize (attr, stacksize) @@ -51,9 +47,9 @@ strong_alias (__pthread_attr_setstacksize, pthread_attr_setstacksize) #else # include versioned_symbol (libpthread, __pthread_attr_setstacksize, - pthread_attr_setstacksize, NEW_VERNUM); + pthread_attr_setstacksize, GLIBC_2_3_3); -# if SHLIB_COMPAT(libpthread, GLIBC_2_1, NEW_VERNUM) +# if SHLIB_COMPAT(libpthread, GLIBC_2_1, GLIBC_2_3_3) int __old_pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize) @@ -67,10 +63,6 @@ __old_pthread_attr_setstacksize (pthread_attr_t *attr, size_t stacksize) if (stacksize < 16384) return EINVAL; -# ifdef STACKSIZE_ADJUST - STACKSIZE_ADJUST; -# endif - iattr->stacksize = stacksize; return 0; diff --git a/nptl/pthread_barrier_wait.c b/nptl/pthread_barrier_wait.c deleted file mode 100644 index c6b563f242..0000000000 --- a/nptl/pthread_barrier_wait.c +++ /dev/null @@ -1,77 +0,0 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include - - -/* Wait on barrier. */ -int -pthread_barrier_wait (barrier) - pthread_barrier_t *barrier; -{ - struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier; - int result = 0; - - /* Make sure we are alone. */ - lll_lock (ibarrier->lock); - - /* One more arrival. */ - --ibarrier->left; - - /* Are these all? */ - if (ibarrier->left == 0) - { - /* Yes. Increment the event counter to avoid invalid wake-ups and - tell the current waiters that it is their turn. */ - ++ibarrier->curr_event; - - /* Wake up everybody. */ - lll_futex_wake (&ibarrier->curr_event, INT_MAX); - - /* This is the thread which finished the serialization. */ - result = PTHREAD_BARRIER_SERIAL_THREAD; - } - else - { - /* The number of the event we are waiting for. The barrier's event - number must be bumped before we continue. */ - unsigned int event = ibarrier->curr_event; - - /* Before suspending, make the barrier available to others. */ - lll_unlock (ibarrier->lock); - - /* Wait for the event counter of the barrier to change. */ - do - lll_futex_wait (&ibarrier->curr_event, event); - while (event == ibarrier->curr_event); - } - - /* Make sure the init_count is stored locally or in a register. */ - unsigned int init_count = ibarrier->init_count; - - /* If this was the last woken thread, unlock. */ - if (atomic_increment_val (&ibarrier->left) == init_count) - /* We are done. */ - lll_unlock (ibarrier->lock); - - return result; -} diff --git a/nptl/pthread_cond_broadcast.c b/nptl/pthread_cond_broadcast.c deleted file mode 100644 index 2b8b5460f4..0000000000 --- a/nptl/pthread_cond_broadcast.c +++ /dev/null @@ -1,86 +0,0 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include -#include - -#include -#include - - -int -__pthread_cond_broadcast (cond) - pthread_cond_t *cond; -{ - /* Make sure we are alone. */ - lll_mutex_lock (cond->__data.__lock); - - /* Are there any waiters to be woken? */ - if (cond->__data.__total_seq > cond->__data.__wakeup_seq) - { - /* Yes. Mark them all as woken. */ - cond->__data.__wakeup_seq = cond->__data.__total_seq; - cond->__data.__woken_seq = cond->__data.__total_seq; - cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2; - int futex_val = cond->__data.__futex; - /* Signal that a broadcast happened. */ - ++cond->__data.__broadcast_seq; - - /* We are done. */ - lll_mutex_unlock (cond->__data.__lock); - - /* Do not use requeue for pshared condvars. */ - if (cond->__data.__mutex == (void *) ~0l) - goto wake_all; - - /* Wake everybody. */ - pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; - - /* XXX: Kernel so far doesn't support requeue to PI futex. */ - if (__builtin_expect (mut->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP, - 0)) - goto wake_all; - - /* lll_futex_requeue returns 0 for success and non-zero - for errors. */ - if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, - INT_MAX, &mut->__data.__lock, - futex_val), 0)) - { - /* The requeue functionality is not available. */ - wake_all: - lll_futex_wake (&cond->__data.__futex, INT_MAX); - } - - /* That's all. */ - return 0; - } - - /* We are done. */ - lll_mutex_unlock (cond->__data.__lock); - - return 0; -} - -versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, - GLIBC_2_3_2); diff --git a/nptl/pthread_cond_signal.c b/nptl/pthread_cond_signal.c deleted file mode 100644 index 5a9bbcad91..0000000000 --- a/nptl/pthread_cond_signal.c +++ /dev/null @@ -1,61 +0,0 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include -#include - -#include -#include - - -int -__pthread_cond_signal (cond) - pthread_cond_t *cond; -{ - /* Make sure we are alone. */ - lll_mutex_lock (cond->__data.__lock); - - /* Are there any waiters to be woken? */ - if (cond->__data.__total_seq > cond->__data.__wakeup_seq) - { - /* Yes. Mark one of them as woken. */ - ++cond->__data.__wakeup_seq; - ++cond->__data.__futex; - - /* Wake one. */ - if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex, 1, - 1, &cond->__data.__lock), - 0)) - return 0; - - lll_futex_wake (&cond->__data.__futex, 1); - } - - /* We are done. */ - lll_mutex_unlock (cond->__data.__lock); - - return 0; -} - -versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, - GLIBC_2_3_2); diff --git a/nptl/pthread_cond_timedwait.c b/nptl/pthread_cond_timedwait.c deleted file mode 100644 index fdbf43eae8..0000000000 --- a/nptl/pthread_cond_timedwait.c +++ /dev/null @@ -1,214 +0,0 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include -#include - -#include - - -/* Cleanup handler, defined in pthread_cond_wait.c. */ -extern void __condvar_cleanup (void *arg) - __attribute__ ((visibility ("hidden"))); - -struct _condvar_cleanup_buffer -{ - int oldtype; - pthread_cond_t *cond; - pthread_mutex_t *mutex; - unsigned int bc_seq; -}; - -int -__pthread_cond_timedwait (cond, mutex, abstime) - pthread_cond_t *cond; - pthread_mutex_t *mutex; - const struct timespec *abstime; -{ - struct _pthread_cleanup_buffer buffer; - struct _condvar_cleanup_buffer cbuffer; - int result = 0; - - /* Catch invalid parameters. */ - if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) - return EINVAL; - - /* Make sure we are along. */ - lll_mutex_lock (cond->__data.__lock); - - /* Now we can release the mutex. */ - int err = __pthread_mutex_unlock_usercnt (mutex, 0); - if (err) - { - lll_mutex_unlock (cond->__data.__lock); - return err; - } - - /* We have one new user of the condvar. */ - ++cond->__data.__total_seq; - ++cond->__data.__futex; - cond->__data.__nwaiters += 1 << COND_CLOCK_BITS; - - /* Remember the mutex we are using here. If there is already a - different address store this is a bad user bug. Do not store - anything for pshared condvars. */ - if (cond->__data.__mutex != (void *) ~0l) - cond->__data.__mutex = mutex; - - /* Prepare structure passed to cancellation handler. */ - cbuffer.cond = cond; - cbuffer.mutex = mutex; - - /* Before we block we enable cancellation. Therefore we have to - install a cancellation handler. */ - __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); - - /* The current values of the wakeup counter. The "woken" counter - must exceed this value. */ - unsigned long long int val; - unsigned long long int seq; - val = seq = cond->__data.__wakeup_seq; - /* Remember the broadcast counter. */ - cbuffer.bc_seq = cond->__data.__broadcast_seq; - - while (1) - { - struct timespec rt; - { -#ifdef __NR_clock_gettime - INTERNAL_SYSCALL_DECL (err); - int ret; - ret = INTERNAL_SYSCALL (clock_gettime, err, 2, - (cond->__data.__nwaiters - & ((1 << COND_CLOCK_BITS) - 1)), - &rt); -# ifndef __ASSUME_POSIX_TIMERS - if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0)) - { - struct timeval tv; - (void) gettimeofday (&tv, NULL); - - /* Convert the absolute timeout value to a relative timeout. */ - rt.tv_sec = abstime->tv_sec - tv.tv_sec; - rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; - } - else -# endif - { - /* Convert the absolute timeout value to a relative timeout. */ - rt.tv_sec = abstime->tv_sec - rt.tv_sec; - rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec; - } -#else - /* Get the current time. So far we support only one clock. */ - struct timeval tv; - (void) gettimeofday (&tv, NULL); - - /* Convert the absolute timeout value to a relative timeout. */ - rt.tv_sec = abstime->tv_sec - tv.tv_sec; - rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; -#endif - } - if (rt.tv_nsec < 0) - { - rt.tv_nsec += 1000000000; - --rt.tv_sec; - } - /* Did we already time out? */ - if (__builtin_expect (rt.tv_sec < 0, 0)) - { - if (cbuffer.bc_seq != cond->__data.__broadcast_seq) - goto bc_out; - - goto timeout; - } - - unsigned int futex_val = cond->__data.__futex; - - /* Prepare to wait. Release the condvar futex. */ - lll_mutex_unlock (cond->__data.__lock); - - /* Enable asynchronous cancellation. Required by the standard. */ - cbuffer.oldtype = __pthread_enable_asynccancel (); - - /* Wait until woken by signal or broadcast. */ - err = lll_futex_timed_wait (&cond->__data.__futex, - futex_val, &rt); - - /* Disable asynchronous cancellation. */ - __pthread_disable_asynccancel (cbuffer.oldtype); - - /* We are going to look at shared data again, so get the lock. */ - lll_mutex_lock(cond->__data.__lock); - - /* If a broadcast happened, we are done. */ - if (cbuffer.bc_seq != cond->__data.__broadcast_seq) - goto bc_out; - - /* Check whether we are eligible for wakeup. */ - val = cond->__data.__wakeup_seq; - if (val != seq && cond->__data.__woken_seq != val) - break; - - /* Not woken yet. Maybe the time expired? */ - if (__builtin_expect (err == -ETIMEDOUT, 0)) - { - timeout: - /* Yep. Adjust the counters. */ - ++cond->__data.__wakeup_seq; - ++cond->__data.__futex; - - /* The error value. */ - result = ETIMEDOUT; - break; - } - } - - /* Another thread woken up. */ - ++cond->__data.__woken_seq; - - bc_out: - - cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; - - /* If pthread_cond_destroy was called on this variable already, - notify the pthread_cond_destroy caller all waiters have left - and it can be successfully destroyed. */ - if (cond->__data.__total_seq == -1ULL - && cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) - lll_futex_wake (&cond->__data.__nwaiters, 1); - - /* We are done with the condvar. */ - lll_mutex_unlock (cond->__data.__lock); - - /* The cancellation handling is back to normal, remove the handler. */ - __pthread_cleanup_pop (&buffer, 0); - - /* Get the mutex before returning. */ - err = __pthread_mutex_cond_lock (mutex); - - return err ?: result; -} - -versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, - GLIBC_2_3_2); diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c deleted file mode 100644 index f5f5cec5a8..0000000000 --- a/nptl/pthread_cond_wait.c +++ /dev/null @@ -1,191 +0,0 @@ -/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include -#include - -#include - - -struct _condvar_cleanup_buffer -{ - int oldtype; - pthread_cond_t *cond; - pthread_mutex_t *mutex; - unsigned int bc_seq; -}; - - -void -__attribute__ ((visibility ("hidden"))) -__condvar_cleanup (void *arg) -{ - struct _condvar_cleanup_buffer *cbuffer = - (struct _condvar_cleanup_buffer *) arg; - unsigned int destroying; - - /* We are going to modify shared data. */ - lll_mutex_lock (cbuffer->cond->__data.__lock); - - if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq) - { - /* This thread is not waiting anymore. Adjust the sequence counters - appropriately. We do not increment WAKEUP_SEQ if this would - bump it over the value of TOTAL_SEQ. This can happen if a thread - was woken and then canceled. */ - if (cbuffer->cond->__data.__wakeup_seq - < cbuffer->cond->__data.__total_seq) - { - ++cbuffer->cond->__data.__wakeup_seq; - ++cbuffer->cond->__data.__futex; - } - ++cbuffer->cond->__data.__woken_seq; - } - - cbuffer->cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; - - /* If pthread_cond_destroy was called on this variable already, - notify the pthread_cond_destroy caller all waiters have left - and it can be successfully destroyed. */ - destroying = 0; - if (cbuffer->cond->__data.__total_seq == -1ULL - && cbuffer->cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) - { - lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1); - destroying = 1; - } - - /* We are done. */ - lll_mutex_unlock (cbuffer->cond->__data.__lock); - - /* Wake everybody to make sure no condvar signal gets lost. */ - if (! destroying) - lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX); - - /* Get the mutex before returning unless asynchronous cancellation - is in effect. */ - __pthread_mutex_cond_lock (cbuffer->mutex); -} - - -int -__pthread_cond_wait (cond, mutex) - pthread_cond_t *cond; - pthread_mutex_t *mutex; -{ - struct _pthread_cleanup_buffer buffer; - struct _condvar_cleanup_buffer cbuffer; - int err; - - /* Make sure we are along. */ - lll_mutex_lock (cond->__data.__lock); - - /* Now we can release the mutex. */ - err = __pthread_mutex_unlock_usercnt (mutex, 0); - if (__builtin_expect (err, 0)) - { - lll_mutex_unlock (cond->__data.__lock); - return err; - } - - /* We have one new user of the condvar. */ - ++cond->__data.__total_seq; - ++cond->__data.__futex; - cond->__data.__nwaiters += 1 << COND_CLOCK_BITS; - - /* Remember the mutex we are using here. If there is already a - different address store this is a bad user bug. Do not store - anything for pshared condvars. */ - if (cond->__data.__mutex != (void *) ~0l) - cond->__data.__mutex = mutex; - - /* Prepare structure passed to cancellation handler. */ - cbuffer.cond = cond; - cbuffer.mutex = mutex; - - /* Before we block we enable cancellation. Therefore we have to - install a cancellation handler. */ - __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); - - /* The current values of the wakeup counter. The "woken" counter - must exceed this value. */ - unsigned long long int val; - unsigned long long int seq; - val = seq = cond->__data.__wakeup_seq; - /* Remember the broadcast counter. */ - cbuffer.bc_seq = cond->__data.__broadcast_seq; - - do - { - unsigned int futex_val = cond->__data.__futex; - - /* Prepare to wait. Release the condvar futex. */ - lll_mutex_unlock (cond->__data.__lock); - - /* Enable asynchronous cancellation. Required by the standard. */ - cbuffer.oldtype = __pthread_enable_asynccancel (); - - /* Wait until woken by signal or broadcast. */ - lll_futex_wait (&cond->__data.__futex, futex_val); - - /* Disable asynchronous cancellation. */ - __pthread_disable_asynccancel (cbuffer.oldtype); - - /* We are going to look at shared data again, so get the lock. */ - lll_mutex_lock (cond->__data.__lock); - - /* If a broadcast happened, we are done. */ - if (cbuffer.bc_seq != cond->__data.__broadcast_seq) - goto bc_out; - - /* Check whether we are eligible for wakeup. */ - val = cond->__data.__wakeup_seq; - } - while (val == seq || cond->__data.__woken_seq == val); - - /* Another thread woken up. */ - ++cond->__data.__woken_seq; - - bc_out: - - cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; - - /* If pthread_cond_destroy was called on this varaible already, - notify the pthread_cond_destroy caller all waiters have left - and it can be successfully destroyed. */ - if (cond->__data.__total_seq == -1ULL - && cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) - lll_futex_wake (&cond->__data.__nwaiters, 1); - - /* We are done with the condvar. */ - lll_mutex_unlock (cond->__data.__lock); - - /* The cancellation handling is back to normal, remove the handler. */ - __pthread_cleanup_pop (&buffer, 0); - - /* Get the mutex before returning. */ - return __pthread_mutex_cond_lock (mutex); -} - -versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, - GLIBC_2_3_2); diff --git a/nptl/pthread_getattr_np.c b/nptl/pthread_getattr_np.c index 4bdc7b5b15..f6cd8899d8 100644 --- a/nptl/pthread_getattr_np.c +++ b/nptl/pthread_getattr_np.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -168,8 +168,12 @@ pthread_getattr_np (thread_id, attr) { free (cpuset); if (ret == ENOSYS) - /* There is no such functionality. */ - ret = 0; + { + /* There is no such functionality. */ + ret = 0; + iattr->cpuset = NULL; + iattr->cpusetsize = 0; + } } } diff --git a/nptl/pthread_getcpuclockid.c b/nptl/pthread_getcpuclockid.c deleted file mode 100644 index 8506f94eb4..0000000000 --- a/nptl/pthread_getcpuclockid.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -#include -#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; - -#ifdef CLOCK_THREAD_CPUTIME_ID - /* We need to store the thread ID in the CLOCKID variable together - with a number identifying the clock. We reserve the low 3 bits - for the clock ID and the rest for the thread ID. This is - problematic if the thread ID is too large. But 29 bits should be - fine. - - If some day more clock IDs are needed the ID part can be - enlarged. The IDs are entirely internal. */ - if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE)) - return ERANGE; - - /* Store the number. */ - *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE); - - return 0; -#else - /* We don't have a timer for that. */ - return ENOENT; -#endif -} diff --git a/nptl/pthread_mutex_lock.c b/nptl/pthread_mutex_lock.c index 52cc47f4cc..1c3ee4fe25 100644 --- a/nptl/pthread_mutex_lock.c +++ b/nptl/pthread_mutex_lock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -127,6 +127,8 @@ __pthread_mutex_lock (mutex) int newval = id; #ifdef NO_INCR newval |= FUTEX_WAITERS; +#else + newval |= (oldval & FUTEX_WAITERS); #endif newval diff --git a/nptl/pthread_mutex_timedlock.c b/nptl/pthread_mutex_timedlock.c index c8e6b8507a..8fd681c6ef 100644 --- a/nptl/pthread_mutex_timedlock.c +++ b/nptl/pthread_mutex_timedlock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2004,2005,2006,2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -119,9 +119,11 @@ pthread_mutex_timedlock (mutex, abstime) if ((oldval & FUTEX_OWNER_DIED) != 0) { /* The previous owner died. Try locking the mutex. */ - int newval + int newval = id | (oldval & FUTEX_WAITERS); + + newval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, - id, oldval); + newval, oldval); if (newval != oldval) { oldval = newval; diff --git a/nptl/pthread_mutex_trylock.c b/nptl/pthread_mutex_trylock.c index 94d519233b..66aca8e4b2 100644 --- a/nptl/pthread_mutex_trylock.c +++ b/nptl/pthread_mutex_trylock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -91,9 +91,11 @@ __pthread_mutex_trylock (mutex) if ((oldval & FUTEX_OWNER_DIED) != 0) { /* The previous owner died. Try locking the mutex. */ - int newval + int newval = id | (oldval & FUTEX_WAITERS); + + newval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock, - id, oldval); + newval, oldval); if (newval != oldval) { diff --git a/nptl/pthread_once.c b/nptl/pthread_once.c deleted file mode 100644 index 9b2cef8645..0000000000 --- a/nptl/pthread_once.c +++ /dev/null @@ -1,54 +0,0 @@ -/* Copyright (C) 2002 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include "pthreadP.h" -#include - - - -static lll_lock_t once_lock = LLL_LOCK_INITIALIZER; - - -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) - { - lll_lock (once_lock); - - /* XXX This implementation is not complete. It doesn't take - cancelation and fork into account. */ - if (*once_control == PTHREAD_ONCE_INIT) - { - init_routine (); - - *once_control = !PTHREAD_ONCE_INIT; - } - - lll_unlock (once_lock); - } - - return 0; -} -strong_alias (__pthread_once, pthread_once) diff --git a/nptl/pthread_rwlock_rdlock.c b/nptl/pthread_rwlock_rdlock.c deleted file mode 100644 index e225d7030d..0000000000 --- a/nptl/pthread_rwlock_rdlock.c +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include - - -/* Acquire read lock for RWLOCK. */ -int -__pthread_rwlock_rdlock (rwlock) - pthread_rwlock_t *rwlock; -{ - int result = 0; - - /* Make sure we are along. */ - lll_mutex_lock (rwlock->__data.__lock); - - while (1) - { - /* Get the rwlock if there is no writer... */ - if (rwlock->__data.__writer == 0 - /* ...and if either no writer is waiting or we prefer readers. */ - && (!rwlock->__data.__nr_writers_queued - || rwlock->__data.__flags == 0)) - { - /* Increment the reader counter. Avoid overflow. */ - if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0)) - { - /* Overflow on number of readers. */ - --rwlock->__data.__nr_readers; - result = EAGAIN; - } - - break; - } - - /* Make sure we are not holding the rwlock as a writer. This is - a deadlock situation we recognize and report. */ - if (__builtin_expect (rwlock->__data.__writer - == THREAD_GETMEM (THREAD_SELF, tid), 0)) - { - result = EDEADLK; - break; - } - - /* Remember that we are a reader. */ - if (__builtin_expect (++rwlock->__data.__nr_readers_queued == 0, 0)) - { - /* Overflow on number of queued readers. */ - --rwlock->__data.__nr_readers_queued; - result = EAGAIN; - break; - } - - int waitval = rwlock->__data.__readers_wakeup; - - /* Free the lock. */ - lll_mutex_unlock (rwlock->__data.__lock); - - /* Wait for the writer to finish. */ - lll_futex_wait (&rwlock->__data.__readers_wakeup, waitval); - - /* Get the lock. */ - lll_mutex_lock (rwlock->__data.__lock); - - --rwlock->__data.__nr_readers_queued; - } - - /* We are done, free the lock. */ - lll_mutex_unlock (rwlock->__data.__lock); - - return result; -} - -weak_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) -strong_alias (__pthread_rwlock_rdlock, __pthread_rwlock_rdlock_internal) diff --git a/nptl/pthread_rwlock_timedrdlock.c b/nptl/pthread_rwlock_timedrdlock.c deleted file mode 100644 index 80ea83a3dd..0000000000 --- a/nptl/pthread_rwlock_timedrdlock.c +++ /dev/null @@ -1,137 +0,0 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include - - -/* Try to acquire read lock for RWLOCK or return after specfied time. */ -int -pthread_rwlock_timedrdlock (rwlock, abstime) - pthread_rwlock_t *rwlock; - const struct timespec *abstime; -{ - int result = 0; - - /* Make sure we are along. */ - lll_mutex_lock(rwlock->__data.__lock); - - while (1) - { - int err; - - /* Get the rwlock if there is no writer... */ - if (rwlock->__data.__writer == 0 - /* ...and if either no writer is waiting or we prefer readers. */ - && (!rwlock->__data.__nr_writers_queued - || rwlock->__data.__flags == 0)) - { - /* Increment the reader counter. Avoid overflow. */ - if (++rwlock->__data.__nr_readers == 0) - { - /* Overflow on number of readers. */ - --rwlock->__data.__nr_readers; - result = EAGAIN; - } - - break; - } - - /* Make sure we are not holding the rwlock as a writer. This is - a deadlock situation we recognize and report. */ - if (__builtin_expect (rwlock->__data.__writer - == THREAD_GETMEM (THREAD_SELF, tid), 0)) - { - result = EDEADLK; - break; - } - - /* Make sure the passed in timeout value is valid. Ideally this - test would be executed once. But since it must not be - performed if we would not block at all simply moving the test - to the front is no option. Replicating all the code is - costly while this test is not. */ - if (__builtin_expect (abstime->tv_nsec >= 1000000000 - || abstime->tv_nsec < 0, 0)) - { - result = EINVAL; - break; - } - - /* Get the current time. So far we support only one clock. */ - struct timeval tv; - (void) gettimeofday (&tv, NULL); - - /* Convert the absolute timeout value to a 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; - } - /* Did we already time out? */ - if (rt.tv_sec < 0) - { - /* Yep, return with an appropriate error. */ - result = ETIMEDOUT; - break; - } - - /* Remember that we are a reader. */ - if (++rwlock->__data.__nr_readers_queued == 0) - { - /* Overflow on number of queued readers. */ - --rwlock->__data.__nr_readers_queued; - result = EAGAIN; - break; - } - - int waitval = rwlock->__data.__readers_wakeup; - - /* Free the lock. */ - lll_mutex_unlock (rwlock->__data.__lock); - - /* Wait for the writer to finish. */ - err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup, - waitval, &rt); - - /* Get the lock. */ - lll_mutex_lock (rwlock->__data.__lock); - - --rwlock->__data.__nr_readers_queued; - - /* Did the futex call time out? */ - if (err == -ETIMEDOUT) - { - /* Yep, report it. */ - result = ETIMEDOUT; - break; - } - } - - /* We are done, free the lock. */ - lll_mutex_unlock (rwlock->__data.__lock); - - return result; -} diff --git a/nptl/pthread_rwlock_timedwrlock.c b/nptl/pthread_rwlock_timedwrlock.c deleted file mode 100644 index 97c0598f96..0000000000 --- a/nptl/pthread_rwlock_timedwrlock.c +++ /dev/null @@ -1,127 +0,0 @@ -/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include - - -/* Try to acquire write lock for RWLOCK or return after specfied time. */ -int -pthread_rwlock_timedwrlock (rwlock, abstime) - pthread_rwlock_t *rwlock; - const struct timespec *abstime; -{ - int result = 0; - - /* Make sure we are along. */ - lll_mutex_lock (rwlock->__data.__lock); - - while (1) - { - int err; - - /* Get the rwlock if there is no writer and no reader. */ - if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) - { - /* Mark self as writer. */ - rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); - break; - } - - /* Make sure we are not holding the rwlock as a writer. This is - a deadlock situation we recognize and report. */ - if (__builtin_expect (rwlock->__data.__writer - == THREAD_GETMEM (THREAD_SELF, tid), 0)) - { - result = EDEADLK; - break; - } - - /* Make sure the passed in timeout value is valid. Ideally this - test would be executed once. But since it must not be - performed if we would not block at all simply moving the test - to the front is no option. Replicating all the code is - costly while this test is not. */ - if (__builtin_expect (abstime->tv_nsec >= 1000000000 - || abstime->tv_nsec < 0, 0)) - { - result = EINVAL; - break; - } - - /* Get the current time. So far we support only one clock. */ - struct timeval tv; - (void) gettimeofday (&tv, NULL); - - /* Convert the absolute timeout value to a 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; - } - /* Did we already time out? */ - if (rt.tv_sec < 0) - { - result = ETIMEDOUT; - break; - } - - /* Remember that we are a writer. */ - if (++rwlock->__data.__nr_writers_queued == 0) - { - /* Overflow on number of queued writers. */ - --rwlock->__data.__nr_writers_queued; - result = EAGAIN; - break; - } - - int waitval = rwlock->__data.__writer_wakeup; - - /* Free the lock. */ - lll_mutex_unlock (rwlock->__data.__lock); - - /* Wait for the writer or reader(s) to finish. */ - err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup, - waitval, &rt); - - /* Get the lock. */ - lll_mutex_lock (rwlock->__data.__lock); - - /* To start over again, remove the thread from the writer list. */ - --rwlock->__data.__nr_writers_queued; - - /* Did the futex call time out? */ - if (err == -ETIMEDOUT) - { - result = ETIMEDOUT; - break; - } - } - - /* We are done, free the lock. */ - lll_mutex_unlock (rwlock->__data.__lock); - - return result; -} diff --git a/nptl/pthread_rwlock_unlock.c b/nptl/pthread_rwlock_unlock.c deleted file mode 100644 index 9cae8b6c22..0000000000 --- a/nptl/pthread_rwlock_unlock.c +++ /dev/null @@ -1,57 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include - -/* Unlock RWLOCK. */ -int -__pthread_rwlock_unlock (pthread_rwlock_t *rwlock) -{ - lll_mutex_lock (rwlock->__data.__lock); - if (rwlock->__data.__writer) - rwlock->__data.__writer = 0; - else - --rwlock->__data.__nr_readers; - if (rwlock->__data.__nr_readers == 0) - { - if (rwlock->__data.__nr_writers_queued) - { - ++rwlock->__data.__writer_wakeup; - lll_mutex_unlock (rwlock->__data.__lock); - lll_futex_wake (&rwlock->__data.__writer_wakeup, 1); - return 0; - } - else if (rwlock->__data.__nr_readers_queued) - { - ++rwlock->__data.__readers_wakeup; - lll_mutex_unlock (rwlock->__data.__lock); - lll_futex_wake (&rwlock->__data.__readers_wakeup, INT_MAX); - return 0; - } - } - lll_mutex_unlock (rwlock->__data.__lock); - return 0; -} - -weak_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock) -strong_alias (__pthread_rwlock_unlock, __pthread_rwlock_unlock_internal) diff --git a/nptl/pthread_rwlock_wrlock.c b/nptl/pthread_rwlock_wrlock.c deleted file mode 100644 index 822aeed79c..0000000000 --- a/nptl/pthread_rwlock_wrlock.c +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright (C) 2003 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by Martin Schwidefsky , 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include -#include -#include -#include -#include - - -/* Acquire write lock for RWLOCK. */ -int -__pthread_rwlock_wrlock (rwlock) - pthread_rwlock_t *rwlock; -{ - int result = 0; - - /* Make sure we are along. */ - lll_mutex_lock (rwlock->__data.__lock); - - while (1) - { - /* Get the rwlock if there is no writer and no reader. */ - if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) - { - /* Mark self as writer. */ - rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); - break; - } - - /* Make sure we are not holding the rwlock as a writer. This is - a deadlock situation we recognize and report. */ - if (__builtin_expect (rwlock->__data.__writer - == THREAD_GETMEM (THREAD_SELF, tid), 0)) - { - result = EDEADLK; - break; - } - - /* Remember that we are a writer. */ - if (++rwlock->__data.__nr_writers_queued == 0) - { - /* Overflow on number of queued writers. */ - --rwlock->__data.__nr_writers_queued; - result = EAGAIN; - break; - } - - int waitval = rwlock->__data.__writer_wakeup; - - /* Free the lock. */ - lll_mutex_unlock (rwlock->__data.__lock); - - /* Wait for the writer or reader(s) to finish. */ - lll_futex_wait (&rwlock->__data.__writer_wakeup, waitval); - - /* Get the lock. */ - lll_mutex_lock (rwlock->__data.__lock); - - /* To start over again, remove the thread from the writer list. */ - --rwlock->__data.__nr_writers_queued; - } - - /* We are done, free the lock. */ - lll_mutex_unlock (rwlock->__data.__lock); - - return result; -} - -weak_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) -strong_alias (__pthread_rwlock_wrlock, __pthread_rwlock_wrlock_internal) diff --git a/nptl/pthread_spin_destroy.c b/nptl/pthread_spin_destroy.c deleted file mode 100644 index 4d0109cf02..0000000000 --- a/nptl/pthread_spin_destroy.c +++ /dev/null @@ -1,29 +0,0 @@ -/* Copyright (C) 2002 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include "pthreadP.h" - - -int -pthread_spin_destroy (lock) - pthread_spinlock_t *lock; -{ - /* Nothing to do. */ - return 0; -} diff --git a/nptl/pthread_spin_init.c b/nptl/pthread_spin_init.c deleted file mode 100644 index c2275085e8..0000000000 --- a/nptl/pthread_spin_init.c +++ /dev/null @@ -1,28 +0,0 @@ -/* pthread_spin_init -- initialize a spin lock. Generic version. - Copyright (C) 2003 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include "pthreadP.h" - -int -pthread_spin_init (pthread_spinlock_t *lock, int pshared) -{ - *lock = 0; - return 0; -} diff --git a/nptl/pthread_spin_unlock.c b/nptl/pthread_spin_unlock.c deleted file mode 100644 index f97cadfbd0..0000000000 --- a/nptl/pthread_spin_unlock.c +++ /dev/null @@ -1,30 +0,0 @@ -/* pthread_spin_unlock -- unlock a spin lock. Generic version. - Copyright (C) 2003 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include "pthreadP.h" -#include - -int -pthread_spin_unlock (pthread_spinlock_t *lock) -{ - atomic_full_barrier (); - *lock = 0; - return 0; -} diff --git a/nptl/sysdeps/alpha/tls.h b/nptl/sysdeps/alpha/tls.h index be2430f676..07db15939d 100644 --- a/nptl/sysdeps/alpha/tls.h +++ b/nptl/sysdeps/alpha/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. NPTL/Alpha version. - Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2007 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 @@ -48,6 +48,9 @@ typedef union dtv # error "TLS support is required." #endif +/* Signal that TLS support is available. */ +# define USE_TLS 1 + #ifndef __ASSEMBLER__ /* Get system call information. */ @@ -121,6 +124,29 @@ typedef struct #define THREAD_SETMEM_NC(descr, member, idx, value) \ descr->member[idx] = (value) +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/nptl/sysdeps/i386/tls.h b/nptl/sysdeps/i386/tls.h index d5b3797e69..b3d9142fc5 100644 --- a/nptl/sysdeps/i386/tls.h +++ b/nptl/sysdeps/i386/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. nptl/i386 version. - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2002,2003,2004,2005,2007 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 @@ -51,6 +51,7 @@ typedef struct uintptr_t sysinfo; uintptr_t stack_guard; uintptr_t pointer_guard; + int gscope_flag; } tcbhead_t; # define TLS_MULTIPLE_THREADS_IN_TCB 1 @@ -65,6 +66,9 @@ typedef struct # error "TLS support is required." #endif +/* Signal that TLS support is available. */ +#define USE_TLS 1 + /* Alignment requirement for the stack. For IA-32 this is governed by the SSE memory functions. */ #define STACK_ALIGN 16 @@ -431,6 +435,26 @@ union user_desc_init = THREAD_GETMEM (THREAD_SELF, header.pointer_guard)) +/* Get and set the global scope generation counter in the TCB head. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res; \ + asm volatile ("xchgl %0, %%gs:%P1" \ + : "=r" (__res) \ + : "i" (offsetof (struct pthread, header.gscope_flag)), \ + "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/nptl/sysdeps/ia64/pthread_spin_unlock.c b/nptl/sysdeps/ia64/pthread_spin_unlock.c index 50d9c5f6a8..6232764b13 100644 --- a/nptl/sysdeps/ia64/pthread_spin_unlock.c +++ b/nptl/sysdeps/ia64/pthread_spin_unlock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2003, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2003 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2003. @@ -23,6 +23,6 @@ int pthread_spin_unlock (pthread_spinlock_t *lock) { - __sync_lock_release ((int *) lock); + __sync_lock_release_si ((int *) lock); return 0; } diff --git a/nptl/sysdeps/ia64/tls.h b/nptl/sysdeps/ia64/tls.h index 22a8b08144..a43f096798 100644 --- a/nptl/sysdeps/ia64/tls.h +++ b/nptl/sysdeps/ia64/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. nptl/IA-64 version. - Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2006, 2007 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 @@ -61,6 +61,9 @@ register struct pthread *__thread_self __asm__("r13"); # error "TLS support is required." #endif +/* Signal that TLS support is available. */ +#define USE_TLS 1 + /* Alignment requirement for the stack. */ #define STACK_ALIGN 16 @@ -163,6 +166,29 @@ register struct pthread *__thread_self __asm__("r13"); (((uintptr_t *) ((char *) (descr) + TLS_PRE_TCB_SIZE))[-2] \ = THREAD_GET_POINTER_GUARD ()) +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/nptl/sysdeps/powerpc/tls.h b/nptl/sysdeps/powerpc/tls.h index ddaafe23d0..ad5698c6f8 100644 --- a/nptl/sysdeps/powerpc/tls.h +++ b/nptl/sysdeps/powerpc/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. NPTL/PowerPC version. - Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2007 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 @@ -48,6 +48,9 @@ typedef union dtv # error "TLS support is required." #endif +/* Signal that TLS support is available. */ +# define USE_TLS 1 + #ifndef __ASSEMBLER__ /* Get system call information. */ @@ -180,6 +183,29 @@ register void *__thread_register __asm__ ("r13"); different value to mean unset l_tls_offset. */ # define NO_TLS_OFFSET -1 +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/nptl/sysdeps/pthread/pthread_barrier_wait.c b/nptl/sysdeps/pthread/pthread_barrier_wait.c new file mode 100644 index 0000000000..c6b563f242 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_barrier_wait.c @@ -0,0 +1,77 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include + + +/* Wait on barrier. */ +int +pthread_barrier_wait (barrier) + pthread_barrier_t *barrier; +{ + struct pthread_barrier *ibarrier = (struct pthread_barrier *) barrier; + int result = 0; + + /* Make sure we are alone. */ + lll_lock (ibarrier->lock); + + /* One more arrival. */ + --ibarrier->left; + + /* Are these all? */ + if (ibarrier->left == 0) + { + /* Yes. Increment the event counter to avoid invalid wake-ups and + tell the current waiters that it is their turn. */ + ++ibarrier->curr_event; + + /* Wake up everybody. */ + lll_futex_wake (&ibarrier->curr_event, INT_MAX); + + /* This is the thread which finished the serialization. */ + result = PTHREAD_BARRIER_SERIAL_THREAD; + } + else + { + /* The number of the event we are waiting for. The barrier's event + number must be bumped before we continue. */ + unsigned int event = ibarrier->curr_event; + + /* Before suspending, make the barrier available to others. */ + lll_unlock (ibarrier->lock); + + /* Wait for the event counter of the barrier to change. */ + do + lll_futex_wait (&ibarrier->curr_event, event); + while (event == ibarrier->curr_event); + } + + /* Make sure the init_count is stored locally or in a register. */ + unsigned int init_count = ibarrier->init_count; + + /* If this was the last woken thread, unlock. */ + if (atomic_increment_val (&ibarrier->left) == init_count) + /* We are done. */ + lll_unlock (ibarrier->lock); + + return result; +} diff --git a/nptl/sysdeps/pthread/pthread_cond_broadcast.c b/nptl/sysdeps/pthread/pthread_cond_broadcast.c new file mode 100644 index 0000000000..2b8b5460f4 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_cond_broadcast.c @@ -0,0 +1,86 @@ +/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +int +__pthread_cond_broadcast (cond) + pthread_cond_t *cond; +{ + /* Make sure we are alone. */ + lll_mutex_lock (cond->__data.__lock); + + /* Are there any waiters to be woken? */ + if (cond->__data.__total_seq > cond->__data.__wakeup_seq) + { + /* Yes. Mark them all as woken. */ + cond->__data.__wakeup_seq = cond->__data.__total_seq; + cond->__data.__woken_seq = cond->__data.__total_seq; + cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2; + int futex_val = cond->__data.__futex; + /* Signal that a broadcast happened. */ + ++cond->__data.__broadcast_seq; + + /* We are done. */ + lll_mutex_unlock (cond->__data.__lock); + + /* Do not use requeue for pshared condvars. */ + if (cond->__data.__mutex == (void *) ~0l) + goto wake_all; + + /* Wake everybody. */ + pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex; + + /* XXX: Kernel so far doesn't support requeue to PI futex. */ + if (__builtin_expect (mut->__data.__kind & PTHREAD_MUTEX_PRIO_INHERIT_NP, + 0)) + goto wake_all; + + /* lll_futex_requeue returns 0 for success and non-zero + for errors. */ + if (__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1, + INT_MAX, &mut->__data.__lock, + futex_val), 0)) + { + /* The requeue functionality is not available. */ + wake_all: + lll_futex_wake (&cond->__data.__futex, INT_MAX); + } + + /* That's all. */ + return 0; + } + + /* We are done. */ + lll_mutex_unlock (cond->__data.__lock); + + return 0; +} + +versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast, + GLIBC_2_3_2); diff --git a/nptl/sysdeps/pthread/pthread_cond_signal.c b/nptl/sysdeps/pthread/pthread_cond_signal.c new file mode 100644 index 0000000000..5a9bbcad91 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_cond_signal.c @@ -0,0 +1,61 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +int +__pthread_cond_signal (cond) + pthread_cond_t *cond; +{ + /* Make sure we are alone. */ + lll_mutex_lock (cond->__data.__lock); + + /* Are there any waiters to be woken? */ + if (cond->__data.__total_seq > cond->__data.__wakeup_seq) + { + /* Yes. Mark one of them as woken. */ + ++cond->__data.__wakeup_seq; + ++cond->__data.__futex; + + /* Wake one. */ + if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex, 1, + 1, &cond->__data.__lock), + 0)) + return 0; + + lll_futex_wake (&cond->__data.__futex, 1); + } + + /* We are done. */ + lll_mutex_unlock (cond->__data.__lock); + + return 0; +} + +versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal, + GLIBC_2_3_2); diff --git a/nptl/sysdeps/pthread/pthread_cond_timedwait.c b/nptl/sysdeps/pthread/pthread_cond_timedwait.c new file mode 100644 index 0000000000..fdbf43eae8 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_cond_timedwait.c @@ -0,0 +1,214 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include + + +/* Cleanup handler, defined in pthread_cond_wait.c. */ +extern void __condvar_cleanup (void *arg) + __attribute__ ((visibility ("hidden"))); + +struct _condvar_cleanup_buffer +{ + int oldtype; + pthread_cond_t *cond; + pthread_mutex_t *mutex; + unsigned int bc_seq; +}; + +int +__pthread_cond_timedwait (cond, mutex, abstime) + pthread_cond_t *cond; + pthread_mutex_t *mutex; + const struct timespec *abstime; +{ + struct _pthread_cleanup_buffer buffer; + struct _condvar_cleanup_buffer cbuffer; + int result = 0; + + /* Catch invalid parameters. */ + if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) + return EINVAL; + + /* Make sure we are along. */ + lll_mutex_lock (cond->__data.__lock); + + /* Now we can release the mutex. */ + int err = __pthread_mutex_unlock_usercnt (mutex, 0); + if (err) + { + lll_mutex_unlock (cond->__data.__lock); + return err; + } + + /* We have one new user of the condvar. */ + ++cond->__data.__total_seq; + ++cond->__data.__futex; + cond->__data.__nwaiters += 1 << COND_CLOCK_BITS; + + /* Remember the mutex we are using here. If there is already a + different address store this is a bad user bug. Do not store + anything for pshared condvars. */ + if (cond->__data.__mutex != (void *) ~0l) + cond->__data.__mutex = mutex; + + /* Prepare structure passed to cancellation handler. */ + cbuffer.cond = cond; + cbuffer.mutex = mutex; + + /* Before we block we enable cancellation. Therefore we have to + install a cancellation handler. */ + __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); + + /* The current values of the wakeup counter. The "woken" counter + must exceed this value. */ + unsigned long long int val; + unsigned long long int seq; + val = seq = cond->__data.__wakeup_seq; + /* Remember the broadcast counter. */ + cbuffer.bc_seq = cond->__data.__broadcast_seq; + + while (1) + { + struct timespec rt; + { +#ifdef __NR_clock_gettime + INTERNAL_SYSCALL_DECL (err); + int ret; + ret = INTERNAL_SYSCALL (clock_gettime, err, 2, + (cond->__data.__nwaiters + & ((1 << COND_CLOCK_BITS) - 1)), + &rt); +# ifndef __ASSUME_POSIX_TIMERS + if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (ret, err), 0)) + { + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; + } + else +# endif + { + /* Convert the absolute timeout value to a relative timeout. */ + rt.tv_sec = abstime->tv_sec - rt.tv_sec; + rt.tv_nsec = abstime->tv_nsec - rt.tv_nsec; + } +#else + /* Get the current time. So far we support only one clock. */ + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a relative timeout. */ + rt.tv_sec = abstime->tv_sec - tv.tv_sec; + rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000; +#endif + } + if (rt.tv_nsec < 0) + { + rt.tv_nsec += 1000000000; + --rt.tv_sec; + } + /* Did we already time out? */ + if (__builtin_expect (rt.tv_sec < 0, 0)) + { + if (cbuffer.bc_seq != cond->__data.__broadcast_seq) + goto bc_out; + + goto timeout; + } + + unsigned int futex_val = cond->__data.__futex; + + /* Prepare to wait. Release the condvar futex. */ + lll_mutex_unlock (cond->__data.__lock); + + /* Enable asynchronous cancellation. Required by the standard. */ + cbuffer.oldtype = __pthread_enable_asynccancel (); + + /* Wait until woken by signal or broadcast. */ + err = lll_futex_timed_wait (&cond->__data.__futex, + futex_val, &rt); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (cbuffer.oldtype); + + /* We are going to look at shared data again, so get the lock. */ + lll_mutex_lock(cond->__data.__lock); + + /* If a broadcast happened, we are done. */ + if (cbuffer.bc_seq != cond->__data.__broadcast_seq) + goto bc_out; + + /* Check whether we are eligible for wakeup. */ + val = cond->__data.__wakeup_seq; + if (val != seq && cond->__data.__woken_seq != val) + break; + + /* Not woken yet. Maybe the time expired? */ + if (__builtin_expect (err == -ETIMEDOUT, 0)) + { + timeout: + /* Yep. Adjust the counters. */ + ++cond->__data.__wakeup_seq; + ++cond->__data.__futex; + + /* The error value. */ + result = ETIMEDOUT; + break; + } + } + + /* Another thread woken up. */ + ++cond->__data.__woken_seq; + + bc_out: + + cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; + + /* If pthread_cond_destroy was called on this variable already, + notify the pthread_cond_destroy caller all waiters have left + and it can be successfully destroyed. */ + if (cond->__data.__total_seq == -1ULL + && cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) + lll_futex_wake (&cond->__data.__nwaiters, 1); + + /* We are done with the condvar. */ + lll_mutex_unlock (cond->__data.__lock); + + /* The cancellation handling is back to normal, remove the handler. */ + __pthread_cleanup_pop (&buffer, 0); + + /* Get the mutex before returning. */ + err = __pthread_mutex_cond_lock (mutex); + + return err ?: result; +} + +versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait, + GLIBC_2_3_2); diff --git a/nptl/sysdeps/pthread/pthread_cond_wait.c b/nptl/sysdeps/pthread/pthread_cond_wait.c new file mode 100644 index 0000000000..f5f5cec5a8 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_cond_wait.c @@ -0,0 +1,191 @@ +/* Copyright (C) 2003, 2004, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include + +#include + + +struct _condvar_cleanup_buffer +{ + int oldtype; + pthread_cond_t *cond; + pthread_mutex_t *mutex; + unsigned int bc_seq; +}; + + +void +__attribute__ ((visibility ("hidden"))) +__condvar_cleanup (void *arg) +{ + struct _condvar_cleanup_buffer *cbuffer = + (struct _condvar_cleanup_buffer *) arg; + unsigned int destroying; + + /* We are going to modify shared data. */ + lll_mutex_lock (cbuffer->cond->__data.__lock); + + if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq) + { + /* This thread is not waiting anymore. Adjust the sequence counters + appropriately. We do not increment WAKEUP_SEQ if this would + bump it over the value of TOTAL_SEQ. This can happen if a thread + was woken and then canceled. */ + if (cbuffer->cond->__data.__wakeup_seq + < cbuffer->cond->__data.__total_seq) + { + ++cbuffer->cond->__data.__wakeup_seq; + ++cbuffer->cond->__data.__futex; + } + ++cbuffer->cond->__data.__woken_seq; + } + + cbuffer->cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; + + /* If pthread_cond_destroy was called on this variable already, + notify the pthread_cond_destroy caller all waiters have left + and it can be successfully destroyed. */ + destroying = 0; + if (cbuffer->cond->__data.__total_seq == -1ULL + && cbuffer->cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) + { + lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1); + destroying = 1; + } + + /* We are done. */ + lll_mutex_unlock (cbuffer->cond->__data.__lock); + + /* Wake everybody to make sure no condvar signal gets lost. */ + if (! destroying) + lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX); + + /* Get the mutex before returning unless asynchronous cancellation + is in effect. */ + __pthread_mutex_cond_lock (cbuffer->mutex); +} + + +int +__pthread_cond_wait (cond, mutex) + pthread_cond_t *cond; + pthread_mutex_t *mutex; +{ + struct _pthread_cleanup_buffer buffer; + struct _condvar_cleanup_buffer cbuffer; + int err; + + /* Make sure we are along. */ + lll_mutex_lock (cond->__data.__lock); + + /* Now we can release the mutex. */ + err = __pthread_mutex_unlock_usercnt (mutex, 0); + if (__builtin_expect (err, 0)) + { + lll_mutex_unlock (cond->__data.__lock); + return err; + } + + /* We have one new user of the condvar. */ + ++cond->__data.__total_seq; + ++cond->__data.__futex; + cond->__data.__nwaiters += 1 << COND_CLOCK_BITS; + + /* Remember the mutex we are using here. If there is already a + different address store this is a bad user bug. Do not store + anything for pshared condvars. */ + if (cond->__data.__mutex != (void *) ~0l) + cond->__data.__mutex = mutex; + + /* Prepare structure passed to cancellation handler. */ + cbuffer.cond = cond; + cbuffer.mutex = mutex; + + /* Before we block we enable cancellation. Therefore we have to + install a cancellation handler. */ + __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer); + + /* The current values of the wakeup counter. The "woken" counter + must exceed this value. */ + unsigned long long int val; + unsigned long long int seq; + val = seq = cond->__data.__wakeup_seq; + /* Remember the broadcast counter. */ + cbuffer.bc_seq = cond->__data.__broadcast_seq; + + do + { + unsigned int futex_val = cond->__data.__futex; + + /* Prepare to wait. Release the condvar futex. */ + lll_mutex_unlock (cond->__data.__lock); + + /* Enable asynchronous cancellation. Required by the standard. */ + cbuffer.oldtype = __pthread_enable_asynccancel (); + + /* Wait until woken by signal or broadcast. */ + lll_futex_wait (&cond->__data.__futex, futex_val); + + /* Disable asynchronous cancellation. */ + __pthread_disable_asynccancel (cbuffer.oldtype); + + /* We are going to look at shared data again, so get the lock. */ + lll_mutex_lock (cond->__data.__lock); + + /* If a broadcast happened, we are done. */ + if (cbuffer.bc_seq != cond->__data.__broadcast_seq) + goto bc_out; + + /* Check whether we are eligible for wakeup. */ + val = cond->__data.__wakeup_seq; + } + while (val == seq || cond->__data.__woken_seq == val); + + /* Another thread woken up. */ + ++cond->__data.__woken_seq; + + bc_out: + + cond->__data.__nwaiters -= 1 << COND_CLOCK_BITS; + + /* If pthread_cond_destroy was called on this varaible already, + notify the pthread_cond_destroy caller all waiters have left + and it can be successfully destroyed. */ + if (cond->__data.__total_seq == -1ULL + && cond->__data.__nwaiters < (1 << COND_CLOCK_BITS)) + lll_futex_wake (&cond->__data.__nwaiters, 1); + + /* We are done with the condvar. */ + lll_mutex_unlock (cond->__data.__lock); + + /* The cancellation handling is back to normal, remove the handler. */ + __pthread_cleanup_pop (&buffer, 0); + + /* Get the mutex before returning. */ + return __pthread_mutex_cond_lock (mutex); +} + +versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait, + GLIBC_2_3_2); diff --git a/nptl/sysdeps/pthread/pthread_getcpuclockid.c b/nptl/sysdeps/pthread/pthread_getcpuclockid.c new file mode 100644 index 0000000000..8506f94eb4 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_getcpuclockid.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2000, 2001, 2002, 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include +#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; + +#ifdef CLOCK_THREAD_CPUTIME_ID + /* We need to store the thread ID in the CLOCKID variable together + with a number identifying the clock. We reserve the low 3 bits + for the clock ID and the rest for the thread ID. This is + problematic if the thread ID is too large. But 29 bits should be + fine. + + If some day more clock IDs are needed the ID part can be + enlarged. The IDs are entirely internal. */ + if (pd->tid >= 1 << (8 * sizeof (*clockid) - CLOCK_IDFIELD_SIZE)) + return ERANGE; + + /* Store the number. */ + *clockid = CLOCK_THREAD_CPUTIME_ID | (pd->tid << CLOCK_IDFIELD_SIZE); + + return 0; +#else + /* We don't have a timer for that. */ + return ENOENT; +#endif +} diff --git a/nptl/sysdeps/pthread/pthread_once.c b/nptl/sysdeps/pthread/pthread_once.c new file mode 100644 index 0000000000..9b2cef8645 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_once.c @@ -0,0 +1,54 @@ +/* Copyright (C) 2002 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + + + +static lll_lock_t once_lock = LLL_LOCK_INITIALIZER; + + +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) + { + lll_lock (once_lock); + + /* XXX This implementation is not complete. It doesn't take + cancelation and fork into account. */ + if (*once_control == PTHREAD_ONCE_INIT) + { + init_routine (); + + *once_control = !PTHREAD_ONCE_INIT; + } + + lll_unlock (once_lock); + } + + return 0; +} +strong_alias (__pthread_once, pthread_once) diff --git a/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c b/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c new file mode 100644 index 0000000000..e225d7030d --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_rwlock_rdlock.c @@ -0,0 +1,95 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Acquire read lock for RWLOCK. */ +int +__pthread_rwlock_rdlock (rwlock) + pthread_rwlock_t *rwlock; +{ + int result = 0; + + /* Make sure we are along. */ + lll_mutex_lock (rwlock->__data.__lock); + + while (1) + { + /* Get the rwlock if there is no writer... */ + if (rwlock->__data.__writer == 0 + /* ...and if either no writer is waiting or we prefer readers. */ + && (!rwlock->__data.__nr_writers_queued + || rwlock->__data.__flags == 0)) + { + /* Increment the reader counter. Avoid overflow. */ + if (__builtin_expect (++rwlock->__data.__nr_readers == 0, 0)) + { + /* Overflow on number of readers. */ + --rwlock->__data.__nr_readers; + result = EAGAIN; + } + + break; + } + + /* Make sure we are not holding the rwlock as a writer. This is + a deadlock situation we recognize and report. */ + if (__builtin_expect (rwlock->__data.__writer + == THREAD_GETMEM (THREAD_SELF, tid), 0)) + { + result = EDEADLK; + break; + } + + /* Remember that we are a reader. */ + if (__builtin_expect (++rwlock->__data.__nr_readers_queued == 0, 0)) + { + /* Overflow on number of queued readers. */ + --rwlock->__data.__nr_readers_queued; + result = EAGAIN; + break; + } + + int waitval = rwlock->__data.__readers_wakeup; + + /* Free the lock. */ + lll_mutex_unlock (rwlock->__data.__lock); + + /* Wait for the writer to finish. */ + lll_futex_wait (&rwlock->__data.__readers_wakeup, waitval); + + /* Get the lock. */ + lll_mutex_lock (rwlock->__data.__lock); + + --rwlock->__data.__nr_readers_queued; + } + + /* We are done, free the lock. */ + lll_mutex_unlock (rwlock->__data.__lock); + + return result; +} + +weak_alias (__pthread_rwlock_rdlock, pthread_rwlock_rdlock) +strong_alias (__pthread_rwlock_rdlock, __pthread_rwlock_rdlock_internal) diff --git a/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c b/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c new file mode 100644 index 0000000000..80ea83a3dd --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_rwlock_timedrdlock.c @@ -0,0 +1,137 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Try to acquire read lock for RWLOCK or return after specfied time. */ +int +pthread_rwlock_timedrdlock (rwlock, abstime) + pthread_rwlock_t *rwlock; + const struct timespec *abstime; +{ + int result = 0; + + /* Make sure we are along. */ + lll_mutex_lock(rwlock->__data.__lock); + + while (1) + { + int err; + + /* Get the rwlock if there is no writer... */ + if (rwlock->__data.__writer == 0 + /* ...and if either no writer is waiting or we prefer readers. */ + && (!rwlock->__data.__nr_writers_queued + || rwlock->__data.__flags == 0)) + { + /* Increment the reader counter. Avoid overflow. */ + if (++rwlock->__data.__nr_readers == 0) + { + /* Overflow on number of readers. */ + --rwlock->__data.__nr_readers; + result = EAGAIN; + } + + break; + } + + /* Make sure we are not holding the rwlock as a writer. This is + a deadlock situation we recognize and report. */ + if (__builtin_expect (rwlock->__data.__writer + == THREAD_GETMEM (THREAD_SELF, tid), 0)) + { + result = EDEADLK; + break; + } + + /* Make sure the passed in timeout value is valid. Ideally this + test would be executed once. But since it must not be + performed if we would not block at all simply moving the test + to the front is no option. Replicating all the code is + costly while this test is not. */ + if (__builtin_expect (abstime->tv_nsec >= 1000000000 + || abstime->tv_nsec < 0, 0)) + { + result = EINVAL; + break; + } + + /* Get the current time. So far we support only one clock. */ + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a 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; + } + /* Did we already time out? */ + if (rt.tv_sec < 0) + { + /* Yep, return with an appropriate error. */ + result = ETIMEDOUT; + break; + } + + /* Remember that we are a reader. */ + if (++rwlock->__data.__nr_readers_queued == 0) + { + /* Overflow on number of queued readers. */ + --rwlock->__data.__nr_readers_queued; + result = EAGAIN; + break; + } + + int waitval = rwlock->__data.__readers_wakeup; + + /* Free the lock. */ + lll_mutex_unlock (rwlock->__data.__lock); + + /* Wait for the writer to finish. */ + err = lll_futex_timed_wait (&rwlock->__data.__readers_wakeup, + waitval, &rt); + + /* Get the lock. */ + lll_mutex_lock (rwlock->__data.__lock); + + --rwlock->__data.__nr_readers_queued; + + /* Did the futex call time out? */ + if (err == -ETIMEDOUT) + { + /* Yep, report it. */ + result = ETIMEDOUT; + break; + } + } + + /* We are done, free the lock. */ + lll_mutex_unlock (rwlock->__data.__lock); + + return result; +} diff --git a/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c b/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c new file mode 100644 index 0000000000..97c0598f96 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_rwlock_timedwrlock.c @@ -0,0 +1,127 @@ +/* Copyright (C) 2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Try to acquire write lock for RWLOCK or return after specfied time. */ +int +pthread_rwlock_timedwrlock (rwlock, abstime) + pthread_rwlock_t *rwlock; + const struct timespec *abstime; +{ + int result = 0; + + /* Make sure we are along. */ + lll_mutex_lock (rwlock->__data.__lock); + + while (1) + { + int err; + + /* Get the rwlock if there is no writer and no reader. */ + if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) + { + /* Mark self as writer. */ + rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); + break; + } + + /* Make sure we are not holding the rwlock as a writer. This is + a deadlock situation we recognize and report. */ + if (__builtin_expect (rwlock->__data.__writer + == THREAD_GETMEM (THREAD_SELF, tid), 0)) + { + result = EDEADLK; + break; + } + + /* Make sure the passed in timeout value is valid. Ideally this + test would be executed once. But since it must not be + performed if we would not block at all simply moving the test + to the front is no option. Replicating all the code is + costly while this test is not. */ + if (__builtin_expect (abstime->tv_nsec >= 1000000000 + || abstime->tv_nsec < 0, 0)) + { + result = EINVAL; + break; + } + + /* Get the current time. So far we support only one clock. */ + struct timeval tv; + (void) gettimeofday (&tv, NULL); + + /* Convert the absolute timeout value to a 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; + } + /* Did we already time out? */ + if (rt.tv_sec < 0) + { + result = ETIMEDOUT; + break; + } + + /* Remember that we are a writer. */ + if (++rwlock->__data.__nr_writers_queued == 0) + { + /* Overflow on number of queued writers. */ + --rwlock->__data.__nr_writers_queued; + result = EAGAIN; + break; + } + + int waitval = rwlock->__data.__writer_wakeup; + + /* Free the lock. */ + lll_mutex_unlock (rwlock->__data.__lock); + + /* Wait for the writer or reader(s) to finish. */ + err = lll_futex_timed_wait (&rwlock->__data.__writer_wakeup, + waitval, &rt); + + /* Get the lock. */ + lll_mutex_lock (rwlock->__data.__lock); + + /* To start over again, remove the thread from the writer list. */ + --rwlock->__data.__nr_writers_queued; + + /* Did the futex call time out? */ + if (err == -ETIMEDOUT) + { + result = ETIMEDOUT; + break; + } + } + + /* We are done, free the lock. */ + lll_mutex_unlock (rwlock->__data.__lock); + + return result; +} diff --git a/nptl/sysdeps/pthread/pthread_rwlock_unlock.c b/nptl/sysdeps/pthread/pthread_rwlock_unlock.c new file mode 100644 index 0000000000..9cae8b6c22 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_rwlock_unlock.c @@ -0,0 +1,57 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + +/* Unlock RWLOCK. */ +int +__pthread_rwlock_unlock (pthread_rwlock_t *rwlock) +{ + lll_mutex_lock (rwlock->__data.__lock); + if (rwlock->__data.__writer) + rwlock->__data.__writer = 0; + else + --rwlock->__data.__nr_readers; + if (rwlock->__data.__nr_readers == 0) + { + if (rwlock->__data.__nr_writers_queued) + { + ++rwlock->__data.__writer_wakeup; + lll_mutex_unlock (rwlock->__data.__lock); + lll_futex_wake (&rwlock->__data.__writer_wakeup, 1); + return 0; + } + else if (rwlock->__data.__nr_readers_queued) + { + ++rwlock->__data.__readers_wakeup; + lll_mutex_unlock (rwlock->__data.__lock); + lll_futex_wake (&rwlock->__data.__readers_wakeup, INT_MAX); + return 0; + } + } + lll_mutex_unlock (rwlock->__data.__lock); + return 0; +} + +weak_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock) +strong_alias (__pthread_rwlock_unlock, __pthread_rwlock_unlock_internal) diff --git a/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c b/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c new file mode 100644 index 0000000000..822aeed79c --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_rwlock_wrlock.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2003 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Martin Schwidefsky , 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include + + +/* Acquire write lock for RWLOCK. */ +int +__pthread_rwlock_wrlock (rwlock) + pthread_rwlock_t *rwlock; +{ + int result = 0; + + /* Make sure we are along. */ + lll_mutex_lock (rwlock->__data.__lock); + + while (1) + { + /* Get the rwlock if there is no writer and no reader. */ + if (rwlock->__data.__writer == 0 && rwlock->__data.__nr_readers == 0) + { + /* Mark self as writer. */ + rwlock->__data.__writer = THREAD_GETMEM (THREAD_SELF, tid); + break; + } + + /* Make sure we are not holding the rwlock as a writer. This is + a deadlock situation we recognize and report. */ + if (__builtin_expect (rwlock->__data.__writer + == THREAD_GETMEM (THREAD_SELF, tid), 0)) + { + result = EDEADLK; + break; + } + + /* Remember that we are a writer. */ + if (++rwlock->__data.__nr_writers_queued == 0) + { + /* Overflow on number of queued writers. */ + --rwlock->__data.__nr_writers_queued; + result = EAGAIN; + break; + } + + int waitval = rwlock->__data.__writer_wakeup; + + /* Free the lock. */ + lll_mutex_unlock (rwlock->__data.__lock); + + /* Wait for the writer or reader(s) to finish. */ + lll_futex_wait (&rwlock->__data.__writer_wakeup, waitval); + + /* Get the lock. */ + lll_mutex_lock (rwlock->__data.__lock); + + /* To start over again, remove the thread from the writer list. */ + --rwlock->__data.__nr_writers_queued; + } + + /* We are done, free the lock. */ + lll_mutex_unlock (rwlock->__data.__lock); + + return result; +} + +weak_alias (__pthread_rwlock_wrlock, pthread_rwlock_wrlock) +strong_alias (__pthread_rwlock_wrlock, __pthread_rwlock_wrlock_internal) diff --git a/nptl/sysdeps/pthread/pthread_spin_destroy.c b/nptl/sysdeps/pthread/pthread_spin_destroy.c new file mode 100644 index 0000000000..4d0109cf02 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_spin_destroy.c @@ -0,0 +1,29 @@ +/* Copyright (C) 2002 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + + +int +pthread_spin_destroy (lock) + pthread_spinlock_t *lock; +{ + /* Nothing to do. */ + return 0; +} diff --git a/nptl/sysdeps/pthread/pthread_spin_init.c b/nptl/sysdeps/pthread/pthread_spin_init.c new file mode 100644 index 0000000000..c2275085e8 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_spin_init.c @@ -0,0 +1,28 @@ +/* pthread_spin_init -- initialize a spin lock. Generic version. + Copyright (C) 2003 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" + +int +pthread_spin_init (pthread_spinlock_t *lock, int pshared) +{ + *lock = 0; + return 0; +} diff --git a/nptl/sysdeps/pthread/pthread_spin_unlock.c b/nptl/sysdeps/pthread/pthread_spin_unlock.c new file mode 100644 index 0000000000..f97cadfbd0 --- /dev/null +++ b/nptl/sysdeps/pthread/pthread_spin_unlock.c @@ -0,0 +1,30 @@ +/* pthread_spin_unlock -- unlock a spin lock. Generic version. + Copyright (C) 2003 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, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include "pthreadP.h" +#include + +int +pthread_spin_unlock (pthread_spinlock_t *lock) +{ + atomic_full_barrier (); + *lock = 0; + return 0; +} diff --git a/nptl/sysdeps/s390/tls.h b/nptl/sysdeps/s390/tls.h index 6f6f17b975..8e8f86d64e 100644 --- a/nptl/sysdeps/s390/tls.h +++ b/nptl/sysdeps/s390/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. NPTL/s390 version. - Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2004, 2005, 2007 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 @@ -50,6 +50,7 @@ typedef struct int multiple_threads; uintptr_t sysinfo; uintptr_t stack_guard; + int gscope_flag; } tcbhead_t; # ifndef __s390x__ @@ -66,6 +67,9 @@ typedef struct # error "TLS support is required." #endif +/* Signal that TLS support is available. */ +#define USE_TLS 1 + /* Alignment requirement for the stack. For IA-32 this is governed by the SSE memory functions. */ #define STACK_ALIGN 16 @@ -168,6 +172,29 @@ typedef struct #define THREAD_SET_POINTER_GUARD(value) #define THREAD_COPY_POINTER_GUARD(descr) +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/nptl/sysdeps/sh/tls.h b/nptl/sysdeps/sh/tls.h index d9aa1073b8..2873fe73a8 100644 --- a/nptl/sysdeps/sh/tls.h +++ b/nptl/sysdeps/sh/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. NPTL/SH version. - Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2007 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 @@ -56,6 +56,9 @@ typedef struct # error "TLS support is required." #endif +/* Signal that TLS support is available. */ +# define USE_TLS 1 + #ifndef __ASSEMBLER__ /* Get system call information. */ @@ -150,6 +153,29 @@ typedef struct __asm __volatile ("stc gbr,%0" : "=r" (__tcbp)); \ ((tcbhead_t *) (descr + 1))->pointer_guard = __tcbp->pointer_guard;}) +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/nptl/sysdeps/sparc/tls.h b/nptl/sysdeps/sparc/tls.h index 4fbe426595..90a3e0bf3d 100644 --- a/nptl/sysdeps/sparc/tls.h +++ b/nptl/sysdeps/sparc/tls.h @@ -1,5 +1,5 @@ /* Definitions for thread-local data handling. NPTL/sparc version. - Copyright (C) 2003, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2003, 2005, 2006, 2007 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 @@ -46,9 +46,15 @@ typedef struct dtv_t *dtv; void *self; int multiple_threads; +#if __WORDSIZE == 64 + int gscope_flag; +#endif uintptr_t sysinfo; uintptr_t stack_guard; uintptr_t pointer_guard; +#if __WORDSIZE != 64 + int gscope_flag; +#endif } tcbhead_t; #else /* __ASSEMBLER__ */ @@ -60,6 +66,9 @@ typedef struct # error "TLS support is required." #endif +/* Signal that TLS support is available. */ +#define USE_TLS 1 + #ifndef __ASSEMBLER__ /* Get system call information. */ # include @@ -141,6 +150,29 @@ register struct pthread *__thread_self __asm__("%g7"); # define THREAD_COPY_POINTER_GUARD(descr) \ ((descr)->header.pointer_guard = THREAD_GET_POINTER_GUARD ()) +/* Get and set the global scope generation counter in struct pthread. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res \ + = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \ + THREAD_GSCOPE_FLAG_UNUSED); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + do \ + { \ + THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \ + atomic_write_barrier (); \ + } \ + while (0) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + #endif /* !ASSEMBLER */ #endif /* tls.h */ diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h index 9b27b1ff48..e0718780cc 100644 --- a/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h +++ b/nptl/sysdeps/unix/sysv/linux/alpha/bits/local_lim.h @@ -87,6 +87,3 @@ /* Maximum message queue priority level. */ #define MQ_PRIO_MAX 32768 - -/* Maximum value the semaphore can have. */ -#define SEM_VALUE_MAX (2147483647) diff --git a/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h index be4469c69d..6dadfda206 100644 --- a/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h +++ b/nptl/sysdeps/unix/sysv/linux/alpha/bits/semaphore.h @@ -26,6 +26,9 @@ /* Value returned if `sem_open' failed. */ #define SEM_FAILED ((sem_t *) 0) +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + typedef union { diff --git a/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h index 4b7b29787e..b639ba44af 100644 --- a/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h +++ b/nptl/sysdeps/unix/sysv/linux/bits/local_lim.h @@ -87,6 +87,3 @@ /* Maximum message queue priority level. */ #define MQ_PRIO_MAX 32768 - -/* Maximum value the semaphore can have. */ -#define SEM_VALUE_MAX (2147483647) diff --git a/nptl/sysdeps/unix/sysv/linux/fork.c b/nptl/sysdeps/unix/sysv/linux/fork.c index 840974401b..98bb237c06 100644 --- a/nptl/sysdeps/unix/sysv/linux/fork.c +++ b/nptl/sysdeps/unix/sysv/linux/fork.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -167,8 +167,11 @@ __libc_fork (void) allp->handler->child_handler (); /* Note that we do not have to wake any possible waiter. - This is the only thread in the new process. */ - --allp->handler->refcntr; + 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 diff --git a/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h index 934493c308..e6c5d845ce 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/bits/semaphore.h @@ -28,6 +28,9 @@ /* Value returned if `sem_open' failed. */ #define SEM_FAILED ((sem_t *) 0) +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + typedef union { diff --git a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S index aa1f9f41ca..bf70e17fca 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/i386/i486/sem_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -79,10 +79,7 @@ sem_timedwait: jae 6f cfi_offset(3, -16) /* %ebx */ -7: call __pthread_enable_asynccancel - movl %eax, 8(%esp) - - xorl %ecx, %ecx +7: xorl %ecx, %ecx movl %esp, %ebx movl %ecx, %edx movl $SYS_gettimeofday, %eax @@ -105,6 +102,10 @@ sem_timedwait: movl %ecx, (%esp) /* Store relative timeout. */ movl %edx, 4(%esp) + + call __pthread_enable_asynccancel + movl %eax, 8(%esp) + movl 28(%esp), %ebx xorl %ecx, %ecx movl %esp, %esi diff --git a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h index 1cd4b9b8b6..d60dcd33d5 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/sysdep-cancel.h @@ -58,7 +58,6 @@ # define SAVE_OLDTYPE_3 SAVE_OLDTYPE_2 # define SAVE_OLDTYPE_4 SAVE_OLDTYPE_2 # define SAVE_OLDTYPE_5 SAVE_OLDTYPE_2 -# define SAVE_OLDTYPE_6 SAVE_OLDTYPE_2 # define PUSHCARGS_0 /* No arguments to push. */ # define DOCARGS_0 /* No arguments to frob. */ @@ -102,14 +101,6 @@ # define _POPCARGS_5 _POPCARGS_4; popl %edi; \ cfi_adjust_cfa_offset (-4); cfi_restore (edi); -# define PUSHCARGS_6 _PUSHCARGS_6 -# define DOCARGS_6 _DOARGS_6 (44) -# define POPCARGS_6 _POPCARGS_6 -# define _PUSHCARGS_6 pushl %ebp; cfi_adjust_cfa_offset (4); \ - cfi_rel_offset (ebp, 0); _PUSHCARGS_5 -# define _POPCARGS_6 _POPCARGS_5; popl %ebp; \ - cfi_adjust_cfa_offset (-4); cfi_restore (ebp); - # ifdef IS_IN_libpthread # define CENABLE call __pthread_enable_asynccancel; # define CDISABLE call __pthread_disable_asynccancel @@ -131,7 +122,6 @@ # define POPSTATE_3 POPSTATE_2 # define POPSTATE_4 POPSTATE_3 # define POPSTATE_5 POPSTATE_4 -# define POPSTATE_6 POPSTATE_5 # ifndef __ASSEMBLER__ # define SINGLE_THREAD_P \ diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h index 83db31efcb..f837250b95 100644 --- a/nptl/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h +++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/local_lim.h @@ -87,6 +87,3 @@ /* Maximum message queue priority level. */ #define MQ_PRIO_MAX 32768 - -/* Maximum value the semaphore can have. */ -#define SEM_VALUE_MAX (2147483647) diff --git a/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h index 0684aebe24..2329e98667 100644 --- a/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h +++ b/nptl/sysdeps/unix/sysv/linux/ia64/bits/semaphore.h @@ -28,6 +28,9 @@ /* Value returned if `sem_open' failed. */ #define SEM_FAILED ((sem_t *) 0) +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + typedef union { diff --git a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c index 3e88ee1866..30ef991bd0 100644 --- a/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c +++ b/nptl/sysdeps/unix/sysv/linux/lowlevelrobustlock.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2006 Free Software Foundation, Inc. +/* Copyright (C) 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Jakub Jelinek , 2006. @@ -30,6 +30,10 @@ __lll_robust_lock_wait (int *futex) 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 (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) @@ -41,6 +45,9 @@ __lll_robust_lock_wait (int *futex) continue; lll_futex_wait (futex, newval); + + try: + ; } while ((oldval = atomic_compare_and_exchange_val_acq (futex, tid | FUTEX_WAITERS, @@ -57,6 +64,11 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime) 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; do { @@ -80,7 +92,6 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime) return ETIMEDOUT; /* Wait. */ - int oldval = *futex; if (__builtin_expect (oldval & FUTEX_OWNER_DIED, 0)) return oldval; @@ -90,8 +101,13 @@ __lll_robust_timedlock_wait (int *futex, const struct timespec *abstime) continue; lll_futex_timed_wait (futex, newval, &rt); + + try: + ; } - while (atomic_compare_and_exchange_bool_acq (futex, tid | FUTEX_WAITERS, 0)); + while ((oldval = atomic_compare_and_exchange_val_acq (futex, + tid | FUTEX_WAITERS, + 0)) != 0); return 0; } diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/Versions b/nptl/sysdeps/unix/sysv/linux/powerpc/Versions index 6b5a0362da..9977847984 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/Versions +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/Versions @@ -2,8 +2,4 @@ libpthread { GLIBC_2.3.4 { longjmp; siglongjmp; } - GLIBC_2.6 { - # Changed PTHREAD_STACK_MIN. - pthread_attr_setstack; pthread_attr_setstacksize; - } } diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h deleted file mode 100644 index 02e2d17343..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/local_lim.h +++ /dev/null @@ -1,93 +0,0 @@ -/* Minimum guaranteed maximum values for system limits. Linux/PPC version. - Copyright (C) 1993-1998,2000,2002-2004,2006 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* The kernel header pollutes the namespace with the NR_OPEN symbol - and defines LINK_MAX although filesystems have different maxima. A - similar thing is true for OPEN_MAX: the limit can be changed at - runtime and therefore the macro must not be defined. Remove this - after including the header if necessary. */ -#ifndef NR_OPEN -# define __undef_NR_OPEN -#endif -#ifndef LINK_MAX -# define __undef_LINK_MAX -#endif -#ifndef OPEN_MAX -# define __undef_OPEN_MAX -#endif - -/* The kernel sources contain a file with all the needed information. */ -#include - -/* Have to remove NR_OPEN? */ -#ifdef __undef_NR_OPEN -# undef NR_OPEN -# undef __undef_NR_OPEN -#endif -/* Have to remove LINK_MAX? */ -#ifdef __undef_LINK_MAX -# undef LINK_MAX -# undef __undef_LINK_MAX -#endif -/* Have to remove OPEN_MAX? */ -#ifdef __undef_OPEN_MAX -# undef OPEN_MAX -# undef __undef_OPEN_MAX -#endif - -/* The number of data keys per process. */ -#define _POSIX_THREAD_KEYS_MAX 128 -/* This is the value this implementation supports. */ -#define PTHREAD_KEYS_MAX 1024 - -/* Controlling the iterations of destructors for thread-specific data. */ -#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 -/* Number of iterations this implementation does. */ -#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS - -/* The number of threads per process. */ -#define _POSIX_THREAD_THREADS_MAX 64 -/* We have no predefined limit on the number of threads. */ -#undef PTHREAD_THREADS_MAX - -/* Maximum amount by which a process can descrease its asynchronous I/O - priority level. */ -#define AIO_PRIO_DELTA_MAX 20 - -/* Minimum size for a thread. At least two pages for systems with 64k - pages. */ -#define PTHREAD_STACK_MIN 131072 - -/* Maximum number of timer expiration overruns. */ -#define DELAYTIMER_MAX 2147483647 - -/* Maximum tty name length. */ -#define TTY_NAME_MAX 32 - -/* Maximum login name length. This is arbitrary. */ -#define LOGIN_NAME_MAX 256 - -/* Maximum host name length. */ -#define HOST_NAME_MAX 64 - -/* Maximum message queue priority level. */ -#define MQ_PRIO_MAX 32768 - -/* Maximum value the semaphore can have. */ -#define SEM_VALUE_MAX (2147483647) diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h index c7f121ba5b..8123b418b5 100644 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h +++ b/nptl/sysdeps/unix/sysv/linux/powerpc/bits/semaphore.h @@ -33,6 +33,9 @@ /* Value returned if `sem_open' failed. */ #define SEM_FAILED ((sem_t *) 0) +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + typedef union { diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c deleted file mode 100644 index 2cb0a13bcb..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstack.c +++ /dev/null @@ -1,2 +0,0 @@ -#define NEW_VERNUM GLIBC_2_6 -#include diff --git a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c b/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c deleted file mode 100644 index 9472dd17ef..0000000000 --- a/nptl/sysdeps/unix/sysv/linux/powerpc/pthread_attr_setstacksize.c +++ /dev/null @@ -1,8 +0,0 @@ -#define NEW_VERNUM GLIBC_2_6 -#define STACKSIZE_ADJUST \ - do { \ - size_t ps = __getpagesize (); \ - if (stacksize < 2 * ps) \ - stacksize = 2 * ps; \ - } while (0) -#include diff --git a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h index 6b3d3682da..39db5a3bd4 100644 --- a/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h +++ b/nptl/sysdeps/unix/sysv/linux/rtld-lowlevel.h @@ -1,5 +1,5 @@ /* Defintions for lowlevel handling in ld.so. - Copyright (C) 2006 Free Software Foundation, Inc. + Copyright (C) 2006, 2007 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 diff --git a/nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h index 111462f0fb..ead2663047 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h +++ b/nptl/sysdeps/unix/sysv/linux/s390/bits/semaphore.h @@ -32,6 +32,9 @@ /* Value returned if `sem_open' failed. */ #define SEM_FAILED ((sem_t *) 0) +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + typedef union { diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h index 6b0240243a..17ab562daa 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h +++ b/nptl/sysdeps/unix/sysv/linux/s390/s390-32/sysdep-cancel.h @@ -45,13 +45,7 @@ L(pseudo_cancel): \ bas %r14,0(%r1,%r13); \ lr %r0,%r2; \ LM_##args \ - .if SYS_ify (syscall_name) < 256; \ - svc SYS_ify (syscall_name); \ - .else; \ - lhi %r1,SYS_ify (syscall_name); \ - svc 0; \ - .endif; \ - LR7_##args \ + DO_CALL(syscall_name, args); \ l %r1,2f-0b(%r13); \ lr %r12,%r2; \ lr %r2,%r0; \ @@ -95,7 +89,6 @@ L(pseudo_end): #define STM_3 stm %r2,%r4,8(%r15); #define STM_4 stm %r2,%r5,8(%r15); #define STM_5 stm %r2,%r5,8(%r15); -#define STM_6 stm %r2,%r7,8(%r15); #define LM_0 /* Nothing */ #define LM_1 l %r2,8+96(%r15); @@ -103,18 +96,6 @@ L(pseudo_end): #define LM_3 lm %r2,%r4,8+96(%r15); #define LM_4 lm %r2,%r5,8+96(%r15); #define LM_5 lm %r2,%r5,8+96(%r15); -#define LM_6 lm %r2,%r5,8+96(%r15); \ - cfi_offset (%r7, -68); \ - l %r7,96+96(%r15); - -#define LR7_0 /* Nothing */ -#define LR7_1 /* Nothing */ -#define LR7_2 /* Nothing */ -#define LR7_3 /* Nothing */ -#define LR7_4 /* Nothing */ -#define LR7_5 /* Nothing */ -#define LR7_6 l %r7,28+96(%r15); \ - cfi_restore (%r7); # ifndef __ASSEMBLER__ # define SINGLE_THREAD_P \ diff --git a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h index 70d5a86429..77ce742495 100644 --- a/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h +++ b/nptl/sysdeps/unix/sysv/linux/s390/s390-64/sysdep-cancel.h @@ -42,13 +42,7 @@ L(pseudo_cancel): \ brasl %r14,CENABLE; \ lgr %r0,%r2; \ LM_##args \ - .if SYS_ify (syscall_name) < 256; \ - svc SYS_ify (syscall_name); \ - .else; \ - lghi %r1,SYS_ify (syscall_name); \ - svc 0; \ - .endif; \ - LR7_##args \ + DO_CALL(syscall_name, args); \ lgr %r13,%r2; \ lgr %r2,%r0; \ brasl %r14,CDISABLE; \ @@ -91,7 +85,6 @@ L(pseudo_end): #define STM_3 stmg %r2,%r4,16(%r15); #define STM_4 stmg %r2,%r5,16(%r15); #define STM_5 stmg %r2,%r5,16(%r15); -#define STM_6 stmg %r2,%r7,16(%r15); #define LM_0 /* Nothing */ #define LM_1 lg %r2,16+160(%r15); @@ -99,18 +92,6 @@ L(pseudo_end): #define LM_3 lmg %r2,%r4,16+160(%r15); #define LM_4 lmg %r2,%r5,16+160(%r15); #define LM_5 lmg %r2,%r5,16+160(%r15); -#define LM_6 lmg %r2,%r5,16+160(%r15); \ - cfi_offset (%r7, -104); \ - lg %r7,160+160(%r15); - -#define LR7_0 /* Nothing */ -#define LR7_1 /* Nothing */ -#define LR7_2 /* Nothing */ -#define LR7_3 /* Nothing */ -#define LR7_4 /* Nothing */ -#define LR7_5 /* Nothing */ -#define LR7_6 lg %r7,56+160(%r15); \ - cfi_restore (%r7); # if defined IS_IN_libpthread || !defined NOT_IN_libc # ifndef __ASSEMBLER__ diff --git a/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h index 934493c308..e6c5d845ce 100644 --- a/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h +++ b/nptl/sysdeps/unix/sysv/linux/sh/bits/semaphore.h @@ -28,6 +28,9 @@ /* Value returned if `sem_open' failed. */ #define SEM_FAILED ((sem_t *) 0) +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + typedef union { diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h b/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h index 2576f121c3..e082ea8f04 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h +++ b/nptl/sysdeps/unix/sysv/linux/sparc/bits/local_lim.h @@ -87,6 +87,3 @@ /* Maximum message queue priority level. */ #define MQ_PRIO_MAX 32768 - -/* Maximum value the semaphore can have. */ -#define SEM_VALUE_MAX (2147483647) diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h index 8fd7d344ea..7f3a328326 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h +++ b/nptl/sysdeps/unix/sysv/linux/sparc/bits/semaphore.h @@ -33,6 +33,9 @@ /* Value returned if `sem_open' failed. */ #define SEM_FAILED ((sem_t *) 0) +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + typedef union { diff --git a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c index 55d20eb8f8..7613863bba 100644 --- a/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c +++ b/nptl/sysdeps/unix/sysv/linux/sparc/sparc32/sparcv9/pthread_barrier_wait.c @@ -1 +1 @@ -#include "../../../../../../../pthread_barrier_wait.c" +#include "../../../../../../pthread/pthread_barrier_wait.c" diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h index e973bc5bfb..57edbbbfb3 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/bits/semaphore.h @@ -33,6 +33,9 @@ /* Value returned if `sem_open' failed. */ #define SEM_FAILED ((sem_t *) 0) +/* Maximum value the semaphore can have. */ +#define SEM_VALUE_MAX (2147483647) + typedef union { diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S index 90f10e6f4f..394dec8d82 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002-2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -164,7 +164,7 @@ __lll_mutex_timedlock_wait: 8: /* NB: %edx == 2 */ xorl %eax, %eax LOCK - cmpxchgl %edx, (%rdi) + cmpxchgl %edx, (%r12) jnz 7f 6: addq $16, %rsp diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h index 4030bb7fb8..97085bf018 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/lowlevellock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -35,7 +35,6 @@ #define SYS_futex 202 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 -#define FUTEX_CMP_REQUEUE 4 #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 @@ -151,7 +150,7 @@ LLL_STUB_UNWIND_INFO_END #define lll_futex_wait(futex, val) \ ({ \ int __status; \ - register __typeof (val) _val __asm ("edx") = (val); \ + register __typeof (val) _val asm ("edx") = (val); \ __asm __volatile ("xorq %%r10, %%r10\n\t" \ "syscall" \ : "=a" (__status) \ @@ -164,22 +163,22 @@ LLL_STUB_UNWIND_INFO_END #define lll_futex_timed_wait(futex, val, timeout) \ ({ \ - register const struct timespec *__to __asm ("r10") = timeout; \ + register const struct timespec *__to __asm__ ("r10") = timeout; \ int __status; \ - register __typeof (val) _val __asm ("edx") = (val); \ + register __typeof (val) _val asm ("edx") = (val); \ __asm __volatile ("syscall" \ : "=a" (__status) \ : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAIT), \ "d" (_val), "r" (__to) \ : "memory", "cc", "r11", "cx"); \ - -__status; \ + __status; \ }) #define lll_futex_wake(futex, nr) \ do { \ int __ignore; \ - register __typeof (nr) _nr __asm ("edx") = (nr); \ + register __typeof (nr) _nr asm ("edx") = (nr); \ __asm __volatile ("syscall" \ : "=a" (__ignore) \ : "0" (SYS_futex), "D" (futex), "S" (FUTEX_WAKE), \ @@ -424,21 +423,6 @@ extern int __lll_mutex_unlock_wait (int *__futex) attribute_hidden; : "cx", "r11", "cc", "memory"); }) -/* Returns non-zero if error happened, zero if success. */ -#define lll_futex_requeue(ftx, nr_wake, nr_move, mutex, val) \ - ({ int __res; \ - register int __nr_move __asm ("r10") = nr_move; \ - register void *__mutex __asm ("r8") = mutex; \ - register int __val __asm ("r9") = val; \ - __asm __volatile ("syscall" \ - : "=a" (__res) \ - : "0" (__NR_futex), "D" ((void *) ftx), \ - "S" (FUTEX_CMP_REQUEUE), "d" (nr_wake), \ - "r" (__nr_move), "r" (__mutex), "r" (__val) \ - : "cx", "r11", "cc", "memory"); \ - __res < 0; }) - - #define lll_mutex_islocked(futex) \ (futex != LLL_MUTEX_LOCK_INITIALIZER) diff --git a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S index c44d3f5e77..51136cf2dc 100644 --- a/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S +++ b/nptl/sysdeps/unix/sysv/linux/x86_64/sem_timedwait.S @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2005 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -79,10 +79,7 @@ sem_timedwait: cfi_offset(14, -24) /* %r14 */ jae 6f -7: call __pthread_enable_asynccancel - movl %eax, 16(%rsp) - - xorl %esi, %esi +7: xorl %esi, %esi movq %rsp, %rdi movq $VSYSCALL_ADDR_vgettimeofday, %rax callq *%rax @@ -105,6 +102,9 @@ sem_timedwait: movq %rdi, (%rsp) /* Store relative timeout. */ movq %rsi, 8(%rsp) + call __pthread_enable_asynccancel + movl %eax, 16(%rsp) + movq %rsp, %r10 movq %r12, %rdi xorl %esi, %esi diff --git a/nptl/sysdeps/x86_64/tls.h b/nptl/sysdeps/x86_64/tls.h index 7618573e0b..b6385b135c 100644 --- a/nptl/sysdeps/x86_64/tls.h +++ b/nptl/sysdeps/x86_64/tls.h @@ -1,5 +1,5 @@ /* Definition for thread-local data handling. nptl/x86_64 version. - Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + Copyright (C) 2002,2003,2004,2005,2006,2007 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 @@ -47,6 +47,7 @@ typedef struct dtv_t *dtv; void *self; /* Pointer to the thread descriptor. */ int multiple_threads; + int gscope_flag; uintptr_t sysinfo; uintptr_t stack_guard; uintptr_t pointer_guard; @@ -62,6 +63,9 @@ typedef struct # error "TLS support is required." #endif +/* Signal that TLS support is available. */ +#define USE_TLS 1 + /* Alignment requirement for the stack. */ #define STACK_ALIGN 16 @@ -336,6 +340,26 @@ typedef struct = THREAD_GETMEM (THREAD_SELF, header.pointer_guard)) +/* Get and set the global scope generation counter in the TCB head. */ +#define THREAD_GSCOPE_FLAG_UNUSED 0 +#define THREAD_GSCOPE_FLAG_USED 1 +#define THREAD_GSCOPE_FLAG_WAIT 2 +#define THREAD_GSCOPE_RESET_FLAG() \ + do \ + { int __res; \ + asm volatile ("xchgl %0, %%fs:%P1" \ + : "=r" (__res) \ + : "i" (offsetof (struct pthread, header.gscope_flag)), \ + "0" (THREAD_GSCOPE_FLAG_UNUSED)); \ + if (__res == THREAD_GSCOPE_FLAG_WAIT) \ + lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1); \ + } \ + while (0) +#define THREAD_GSCOPE_SET_FLAG() \ + THREAD_SETMEM (THREAD_SELF, header.gscope_flag, THREAD_GSCOPE_FLAG_USED) +#define THREAD_GSCOPE_WAIT() \ + GL(dl_wait_lookup_done) () + #endif /* __ASSEMBLER__ */ #endif /* tls.h */ diff --git a/nptl/tst-cancel-wrappers.sh b/nptl/tst-cancel-wrappers.sh index d6f16d1ed2..61b9fb52de 100644 --- a/nptl/tst-cancel-wrappers.sh +++ b/nptl/tst-cancel-wrappers.sh @@ -1,6 +1,6 @@ #! /bin/sh # Test whether all cancelable functions are cancelable. -# Copyright (C) 2002, 2003 Free Software Foundation, Inc. +# Copyright (C) 2002, 2003, 2007 Free Software Foundation, Inc. # This file is part of the GNU C Library. # Contributed by Jakub Jelinek , 2002. @@ -26,6 +26,7 @@ C["close"]=1 C["connect"]=1 C["creat"]=1 C["fcntl"]=1 +C["fdatasync"]=1 C["fsync"]=1 C["msgrcv"]=1 C["msgsnd"]=1 diff --git a/nptl/tst-cancel4.c b/nptl/tst-cancel4.c index 73cfa44614..45df6ce076 100644 --- a/nptl/tst-cancel4.c +++ b/nptl/tst-cancel4.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. +/* Copyright (C) 2002, 2003, 2004, 2006, 2007 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper , 2002. @@ -1570,6 +1570,47 @@ tf_fsync (void *arg) } +static void * +tf_fdatasync (void *arg) +{ + if (arg == NULL) + // XXX If somebody can provide a portable test case in which fdatasync() + // blocks we can enable this test to run in both rounds. + abort (); + + tempfd = open ("Makefile", O_RDONLY); + if (tempfd == -1) + { + printf ("%s: cannot open Makefile\n", __FUNCTION__); + exit (1); + } + + int r = pthread_barrier_wait (&b2); + if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: barrier_wait failed\n", __FUNCTION__); + exit (1); + } + + r = pthread_barrier_wait (&b2); + if (r != 0 && r != PTHREAD_BARRIER_SERIAL_THREAD) + { + printf ("%s: 2nd barrier_wait failed\n", __FUNCTION__); + exit (1); + } + + pthread_cleanup_push (cl, NULL); + + fdatasync (tempfd); + + pthread_cleanup_pop (0); + + printf ("%s: fdatasync returned\n", __FUNCTION__); + + exit (1); +} + + static void * tf_msync (void *arg) { @@ -2078,6 +2119,7 @@ static struct ADD_TEST (pread, 2, 1), ADD_TEST (pwrite, 2, 1), ADD_TEST (fsync, 2, 1), + ADD_TEST (fdatasync, 2, 1), ADD_TEST (msync, 2, 1), ADD_TEST (sendto, 2, 1), ADD_TEST (sendmsg, 2, 1), diff --git a/nptl/tst-robust9.c b/nptl/tst-robust9.c new file mode 100644 index 0000000000..1d6ba179be --- /dev/null +++ b/nptl/tst-robust9.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include + + +static pthread_mutex_t m; + +static void * +tf (void *data) +{ + int err = pthread_mutex_lock (&m); + if (err == EOWNERDEAD) + { + err = pthread_mutex_consistent_np (&m); + if (err) + { + puts ("pthread_mutex_consistent_np"); + exit (1); + } + } + else if (err) + { + puts ("pthread_mutex_lock"); + exit (1); + } + printf ("thread%ld got the lock.\n", (long int) data); + sleep (1); + /* exit without unlock */ + return NULL; +} + +static int +do_test (void) +{ + int err, i; + pthread_t t[3]; + pthread_mutexattr_t ma; + + pthread_mutexattr_init (&ma); + err = pthread_mutexattr_setrobust_np (&ma, PTHREAD_MUTEX_ROBUST_NP); + if (err) + { + puts ("pthread_mutexattr_setrobust_np"); + return 1; + } +#ifdef ENABLE_PI + if (pthread_mutexattr_setprotocol (&ma, PTHREAD_PRIO_INHERIT) != 0) + { + puts ("pthread_mutexattr_setprotocol failed"); + return 1; + } +#endif + err = pthread_mutex_init (&m, &ma); +#ifdef ENABLE_PI + if (err == ENOTSUP) + { + puts ("PI robust mutexes not supported"); + return 0; + } +#endif + if (err) + { + puts ("pthread_mutex_init"); + return 1; + } + + for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) + { + err = pthread_create (&t[i], NULL, tf, (void *) (long int) i); + if (err) + { + puts ("pthread_create"); + return 1; + } + } + + for (i = 0; i < sizeof (t) / sizeof (t[0]); i++) + { + err = pthread_join (t[i], NULL); + if (err) + { + puts ("pthread_join"); + return 1; + } + } + return 0; +} + +#define TIMEOUT 5 +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nptl/tst-robustpi9.c b/nptl/tst-robustpi9.c new file mode 100644 index 0000000000..d059aa7d88 --- /dev/null +++ b/nptl/tst-robustpi9.c @@ -0,0 +1,2 @@ +#define ENABLE_PI 1 +#include "tst-robust9.c" diff --git a/nptl/tst-sem10.c b/nptl/tst-sem10.c new file mode 100644 index 0000000000..9f6e870a85 --- /dev/null +++ b/nptl/tst-sem10.c @@ -0,0 +1,88 @@ +/* Copyright (C) 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek , 2007. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include +#include +#include +#include +#include +#include +#include + + +static int +do_test (void) +{ + sem_t s; + if (sem_init (&s, 0, 0) == -1) + { + puts ("sem_init failed"); + return 1; + } + + struct timeval tv; + if (gettimeofday (&tv, NULL) != 0) + { + puts ("gettimeofday failed"); + return 1; + } + + struct timespec ts; + TIMEVAL_TO_TIMESPEC (&tv, &ts); + + /* Set ts to yesterday. */ + ts.tv_sec -= 86400; + + int type_before; + if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_before) != 0) + { + puts ("first pthread_setcanceltype failed"); + return 1; + } + + errno = 0; + if (TEMP_FAILURE_RETRY (sem_timedwait (&s, &ts)) != -1) + { + puts ("sem_timedwait succeeded"); + return 1; + } + if (errno != ETIMEDOUT) + { + printf ("sem_timedwait return errno = %d instead of ETIMEDOUT\n", + errno); + return 1; + } + + int type_after; + if (pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, &type_after) != 0) + { + puts ("second pthread_setcanceltype failed"); + return 1; + } + if (type_after != PTHREAD_CANCEL_DEFERRED) + { + puts ("sem_timedwait changed cancellation type"); + return 1; + } + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/nptl/tst-tls5.h b/nptl/tst-tls5.h index 9a76ab7827..b7c14eb82c 100644 --- a/nptl/tst-tls5.h +++ b/nptl/tst-tls5.h @@ -2,7 +2,7 @@ #include #include -#if HAVE___THREAD +#if USE_TLS && HAVE___THREAD struct tls_obj { -- cgit v1.2.3